Can ng-submit be overridden?

Is there a way to modify ng-submit in order to execute certain functions before running the expression it contains? For instance, I want to:

1) Mark all fields as dirty or touched so that validation is performed on all fields, even if the user skipped some.

2) Validate all fields and prevent submission if any fail validation.

3) Scroll to and focus on the first invalid field if there are any errors.

I've come across a few directives that partially achieve this, creating new element directives. However, none actually override or extend ngSubmit. Is it possible to accomplish this?

Answer №1

Validation in Angular can work even without physically interacting with an element, as demonstrated in point #1. For instance, setting $scope.test = "abcd"; would invalidate the input if it is limited to a maximum length of 3 characters:

<input ng-model="test" ng-maxlength="3">

To achieve point #2, one can simply utilize form.$valid:

<form name="form1" ng-submit="form1.$valid && onSubmit()">
  ...
</form>

If there's more complex pre-submit logic involved, it should be handled within the controller, such as in the onSubmit() function.

However, when the pre-submit logic pertains to the View rather than the ViewModel - like scrolling - creating a custom ngSubmit directive with higher priority can intercept the default submit event handling:

.directive("ngSubmit", function() {
  return {
    require: "?form",
    priority: 10,
    link: {
      pre: function(scope, element, attrs, form) {
        element.on("submit", function(event) {        
          if (form && !form.$valid) {
            event.stopImmediatePropagation();
            event.preventDefault();

            // implement necessary scrolling actions here
          }
        })
      }
    }
  }
});

View Demo

EDIT:

The use of pre-link is crucial in this context due to the order of link function executions. The sequence of execution follows:

1. pre-link of parent or higher priority directive
2. pre-link of child or lower priority directive
3. post-link of child or lower priority directive
4. post-link of parent or higher priority directive

By leveraging higher priority and pre-link, this directive can register element.on("submit", ...) before the built-in ngSubmit, ensuring precedence in event handling.

Answer №2

If you're looking to start coding and meet criteria numbers 1 and 2, this snippet should give you a good foundation and even touch on number 3.

Scrolling to invalid fields is something I haven't explored yet, but it does sound intriguing. You could potentially create a complete "form wrapper directive," although that might be considered excessive.

Personally, I would opt for using a service method called within my controller. Are you considering just scrolling to the first invalid field and focusing on it?

Template

<!-- Form Template -->
<form name="form" novalidate ng-submit="vm.submit(form.$valid, vm.data)">
    <input type="text"
           name="blah"
           ng-model="vm.data.blah"
           ng-model-options="{debounce: {'default': 300, blur: 0}}"
           required
           formnovalidate/>
     <div ng-messages="form.blah.$error"
          ng-messages-include="messages.html"
          ng-if="form.$submitted || form.blah.$touched">
     </div>
    <button type="submit">Submit</button>
</form>

<!-- messages.html -->
<div ng-message="required">This field is required</div>

Controller

vm.data = {};
vm.submit = function(isValid, data) {
    if (!isValid) { 
        // Scroll to bad field
        return; 
    }
    // Perform form submission via service
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

React component experiencing double execution of SetTimeout function

Every time I render the App component, the code inside setTimeout seems to be running twice. I've noticed that setTimeout executes after the call stack is cleared. I wonder if this has any connection to the issue. Could it be related to how React ha ...

javascript trigger not functioning

Currently, I am working with ASP development and incorporating jQuery into my projects. One challenge I've encountered is not being able to utilize the trigger function upon page load. Interestingly, my change function seems to work smoothly, except ...

Even after configuring a proxy, the API calls are still not being redirected to the correct destination

Even after setting up a proxy, the API requests are not being directed to the correct target URL. I've built a chatbot application with create-react-app. My goal is to reroute all API calls originating from http://localhost:3000/ to http://localhost: ...

Issue with Nuxt: Property accessed during rendering without being defined on the instance

As I attempt to create cards for my blog posts, I encountered an issue with a Post component in my code. The cards are displaying like shown in the picture, but without any text. How do I insert text into these cards? Currently, all the text is within attr ...

Ways to invoke foo specifically when either a click event or a focus event is triggered

In my custom directive, I am binding focus and click events to an element: app.directive('mydirective', function () { return { link: function ($scope, $element, $attrs) { $element.bind('click focus', function (e) { f ...

Display Issues with Angular Material Dropdown in Internet Explorer 11

How can I fix the display of Angular Material Dropdown in IE11 to match other browsers? Expectation: https://i.sstatic.net/IksBR.png Reality in IE11:https://i.sstatic.net/uhHXG.png Website information: [example no longer available. AngularJS was replace ...

Preventing users from selecting past dates in HTML input date field

I need help with disabling past dates in an HTML date input field. Even though I am able to restrict selecting past dates on the date picker, I can still save data if I manually type in a previous date (e.g., 12/08/2020). $(document).ready(function() { ...

Initiate and terminate server using supertest

I've developed a server class that looks like this: import express, { Request, Response } from 'express'; export default class Server { server: any; exp: any; constructor() { this.exp = express(); this.exp.get('/' ...

The issue with jquery slideToggle is that it mistakenly opens all divs instead of just the specific div that should

My website has a dynamic page with a variable number of <div> elements. The concept is that users can click on the + symbol, which is represented by an <img> tag, to display the corresponding div. Currently, my code includes: PHP/HTML $plus ...

Adding a class using jQuery based on whether a section is visible or hidden on the screen

Seeking advice on the best approach to take. Division 1 or section - Apply style 1 if division 1 is currently visible on the screen. Division 2 or section - Apply style 1 if division 2 is currently visible on the screen. Division 3 or section - Apply st ...

After sending a GET request in AngularJS, simply scroll down to the bottom of the

Usually, I use something like this: $scope.scrollDown = function(){ $location.hash('bottom'); $anchorScroll(); } While this method works fine in most cases, I've encountered an issue when fetching data for an ng-repeat and trying t ...

Step-by-step guide on clipping a path from an image and adjusting the brightness of the remaining unclipped area

Struggling to use clip-path to create a QR code scanner effect on an image. I've tried multiple approaches but can't seem to get it right. Here's what I'm aiming for: https://i.stack.imgur.com/UFcLQ.png I want to clip a square shape f ...

What is the best way to exclude certain values from Objects in Javascript?

Imagine having an object structured like this: "errors": { "name": { "name": "ValidatorError", "message": "Minimum length 6 characters.", "propert ...

What sets response.setHeader apart from response.writeHead?

When it comes to sending a JSON response from my Nodejs server in my application, I have discovered two different methods. However, I am unsure about the distinctions between them. The first method involves var json = JSON.stringify(result.rows); respons ...

The behavior of Material-UI Drawer varies when used on tablets

Encountering some strange issues with the Material-UI drawer component. It's scrolling horizontally on my iPad, while it scrolls vertically on my MacBook and Android Phone. Expected Result on MacBook: https://i.sstatic.net/txBDf.png On my MacBook, it ...

Ways to convert a JavaScript object's properties into JSON format

I am currently manually going through the properties of my javascript class to create JSON, as shown below. It feels cumbersome and I am looking to automate this process so that I don't have to make changes to the 'toJson' function every tim ...

Pattern for identifying text that exclusively consists of whitespace characters and `<br>` tags

Here is an example of a string: <br /> <br /> <br /> Sometimes the string can look like this: <br /> <br /> Or simply like this: & ...

The Protractor Custom Locator is experiencing difficulty in finding the element

For our project, the automation team is incorporating a custom attribute called 'lid' to elements where unique identification is challenging. A new custom locator method has been developed to find elements using the 'lid' attribute: ...

Why does xpath insist on choosing spaces instead of actual elements?

Here is a list of countries in XML format: <countries> <country> <code>CA</code> <name>Canada</name> </country> ... etc... </countries> I am looking to extract and loop through these nodes, so ...

Which ngTagsInput version is recommended for Angular instead of AngularJs?

After discovering the ngTagsInput framework on this site, I found it to be a very comprehensive library. However, for Angular 8 users like myself, I came across the ngx-chips framework on this page. While ngx-chips seems to work, I noticed that it lacks s ...