Avoid activating form.$invalid when the form loads for the first time

Dealing with this particular structure

    <div ng-controller="FormController as f_ctrl">
    <form ng-submit="f_ctrl.submit()" name="myForm">
    <input type="text" ng-model="f_ctrl.user.username"
            required
            ng-minlength="4"/>
    <input type="text" ng-model="f_ctrl.user.password"/>
    <input type="submit" value="Submit" ng-disabled="myForm.$invalid">
    </form>
</div>

With the following controller setup

    .controller('FormController', [function() {
    var self = this;

    self.submit = function() {
        console.log('User submitted form with ' + self.user.username)
    }
}]);

I am encountering an issue: upon initial page load, there is already a noticeable red border around the username field, even though I have not started entering any text yet. I would like to only highlight invalid fields after the first submission. Is there a way to achieve this using form.$invalid ?

Answer №1

To achieve this, you need to utilize $pristine. This attribute is true when the form controller has not been altered. Therefore, if you modify the data in a textbox, it will become false.

Here's a small example for better understanding:

<div class="form-group" ng-class="{ 'has-error' : userForm.password.$invalid && !userForm.password.$pristine }">
    <input id="passAnime" type="password" name="password" ng-model="user.password" class="form-control input-md" placeholder="Password" tabindex="5" ng-maxlength="25" ng-minlength="6" required>

    <span ng-show="userForm.password.$dirty && userForm.password.$invalid">
        <p ng-show="userForm.password.$error.required" class="error-messages">
             Your password is required.
        </p>
        <p ng-show="userForm.password.$error.minlength" class="error-messages">
            Your password is too short. Minimum of 6 characters required.
        </p>
        <p ng-show="userForm.password.$error.maxlength" class="error-messages">
            Your password is too long. Maximum of 25 characters allowed.
        </p>
    </span>
</div>

Answer №2

Angular provides useful tools to determine if a form (or form field) is $dirty (user has entered data) or if the form is $touched (the input has been blurred). View a demonstration here.

I want to highlight invalid fields only after the first submission.

Regrettably, Angular does not have built-in support for this feature. However, you can easily implement it yourself:

Controller

function FormController() {
  var vm = this;
  vm.submitAttempted = false;
  vm.submit = function(isValid) {
    if (isValid) {
      // perform actions
    } else {
      vm.submitAttempted = true;
    }
  };
}

HTML

<div ng-app='app'>
  <div ng-controller='FormController as vm'>
    <form name='fooForm' ng-submit='vm.submit(fooForm.$valid)' novalidate>
      <label>Username</label>
      <input 
        name='username' 
        type='text' 
        ng-model='vm.user.username'
        required
        ng-minlength='4'
        ng-class="{'invalid': vm.submitAttempted && fooForm.username.$invalid}">
      <br /><br />
      <button type='submit'>Submit</button>
    </form>
  </div>
</div>

CSS

.invalid {
  border-color: red;
}

View Demo


I am facing an issue: upon page load, the username field immediately displays a red border even before any text is inputted.

This may be due to the presence of the following CSS class:

.ng-invalid {
  border-color: red;
}

Angular will consistently assign the ng-invalid class to invalid fields, which cannot be altered. If you do not want all invalid fields to always have a red border, avoid using that class and follow a similar approach outlined above.


Additionally, explore ngMessages.

Answer №3

If you want to remove the default styling on the input field that adds a red border, you can do so by implementing the following CSS:

input:required {
    -moz-box-shadow: none;
    box-shadow: none;
}

To highlight the field when the form is submitted, make sure to assign relevant name attributes to the form and form fields. This way, you can verify if the field is valid and apply a class to your text field if it is invalid:

<input type="text" name="username" ng-class="{ 'invalid-field' : f_ctrl.myForm.username.$invalid && !f_ctrl.myForm.username.$pristine }" required />

f_ctrl.myForm and f_ctrl.myform.username will contain extra properties that can help you determine the validity of the form or fields, as well as whether they have been altered in any way (e.g. f_ctrl.myform.username.$dirty). You can display these properties on your page by adding the following HTML:

<div>
    <pre>{{f_ctrl.myForm | json}}</pre>
</div>

Alternatively, you can output self.myForm to the console from your controller to inspect its properties:

console.log(self.myForm);

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

When attempting to fetch data with a dynamic URL in next.js, the error message "undefined is returned

While fetching data on my main page everything works as expected. However, when trying to fetch data in another folder using the same code but with a dynamic URL, I encounter an error when attempting to use methods on an array. Interestingly, when I consol ...

The Typescript compiler has detected an error with code 2339: The property 'project' is not found on the object type '{}'

Encountering a recurring issue in Angular 2 RC1 that is proving to be quite frustrating. Does anyone have any suggestions on how to resolve this compilation error? The problematic line causing the error is: this.project = res.project; Below is my compon ...

Filtering in AngularJS using the ng-repeat directive allows you to iterate over an object

I am trying to figure out a way to determine if each movie in the array belongs to the selected category. The movies array contains objects with various properties, including a 'categories' property which is an array of categories that the movie ...

Having trouble showing Firebase data on a basic Vue application

I've been working on a simple Vue+Firebase application that allows users to send strings to the Firebase database and have the messages displayed using the "v-for" directive. However, I keep encountering an error message stating: Property or method " ...

There seems to be an issue with the border displaying correctly within the div element

I am currently working on developing a tag input system, but I am encountering some CSS issues. What I am aiming for is to have a green border that surrounds and contains the 2 divs inside it, however, this is not happening as expected. You can see the fi ...

Is there a way to modify the edit button to become a save button and include a cancel button?

Is there a way to toggle between an edit button and a save button, along with a cancel option? $('#edit').click(function() { $(this).hide(); $('#save, #cancel').show(); }); $('#cancel').click(function() { $('#ed ...

AngularJS event listener fired twice

Currently, I am facing a scenario where one controller is sending out the event, while another controller is set up to listen for it. The code looks like this: In controller A, there is a method defined as follows: $scope.process = function () { var t ...

React - Implementing pre-fetching of data prior to rendering

As a beginner in react, I have encountered a best practice dilemma that is causing me to make mistakes. My issue arises when I call an API to get information and then update an array in the state once the response is received. However, in the "render" func ...

The error message "Unauthorized use of the Request header field Authorization" is occurring within the Tastypie framework

Encountering an error with ApiKeyAuthentication on my Tastypie resources when making an HTTP request using AJAX and Tastypie: Error: XMLHttpRequest cannot load http://domain.com/api/v1/item/?format=json&username=popo&api_key=b83d21e2f8bd4952a53d0c ...

Generate an array of JavaScript objects by converting a batch of JSON objects into objects within a Node.js environment

I am working with a prototype class: function customClass(){ this.a=77; } customClass.prototype.getValue = function(){ console.log(this.a); } and I also have an array of JSON objects: var data=[{a:21},{a:22},{a:23}]; Is there a way to cre ...

Guidance on sending Ajax response to JavaScript function in OctoberCMS

In the HTML file of my component, I have created a form. When I submit the form, it triggers an AJAX call to an action defined in the component. Currently, my code is functioning properly and I am receiving a response. However, I now need this response to ...

Namespacing is not applied to dynamic modules in Vuex

I've been tackling a modular vue application that enrolls the modules during compile time. Take a look at the code snippet below - app.js import store from './vue-components/store'; var components = { erp_inventory: true, erp_purc ...

Transforming JavaScript into TypeScript within an Angular 4 component class

Here is the Javascript code I currently have. I need to convert this into a component class within an Angular component. As far as I understand, the Character.prototype.placeAt() code is used to add a new method or attribute to an existing object. In this ...

Despite the div condition not being met, the code inside the div is still being executed

Even when the condition of the div is not met, it still runs the code within the div. <div ng-if = "1==11"> nishant <td><a href="indexForm.jsp?id={{x.id}}" class="btn btn-prima ...

Sending an Ajax request using a dropdown menu

I'm having trouble retrieving a value from my database when a select option is chosen. The select options are generated dynamically from the same database. As a beginner in AJAX requests, I am struggling to figure out why I am only getting a blank re ...

Discover the `.next/server` feature on Vercel - a platform where it seamlessly operates unlike on Netlify

Having trouble accessing .next/server on Vercel when running the build:rss script: { "export": "next export", "build": "next build && npm run export && npm run build:rss", "build:rss": &q ...

Sharing AngularJS Controllers Across Multiple Pages

Is it possible to use the same controller across multiple pages in AngularJS? If so, how can you preload data from the server for each shared page differently? Can ng-init be utilized to address this challenge? ...

Show data based on the chosen destination

Recently, I've been working on creating a simple printer manager to monitor the status of all my printers. Although I have successfully displayed all the data, I'm facing an issue while trying to organize it by location. The error message I keep ...

Vue: Changing the value in the select dropdown causes input fields to reset their content

After setting up a form with input values, I noticed that when using a select element with a v-model to change the dropdown value, the input fields from the previous selections are cleared. This has been a persistent issue for me and is now starting to imp ...

View the outcome of a form submission button within Adobe Analytics

In the classic version of my form, I have a submit button. <form action="" name="frm" method=""> <input type="submit" value="submit"> </input> I implemented a jQuery command to track successful form submissions in Adobe Analytics and ca ...