Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular form validation: ng-show when at least one input is ng-invalid and ng-dirty

I have the following form in an Angular partial:

<form name="submit_entry_form" id="submit_entry_form" ng-submit="submit()" ng-controller="SubmitEntryFormCtrl" novalidate >
    <input type="text" name="first_name" ng-model="first_name" placeholder="First Name" required/><br />
    <input type="text" name="last_name" ng-model="last_name" placeholder="Last Name" required/><br />
    <input type="text" name="email" ng-model="email" placeholder="Email Address" required/><br />
    <input type="text" name="confirm_email" ng-model="confirm_email" placeholder="Confirm Email Address" required/><br />
    <span ng-show="submit_entry_form.$invalid">Error!</span>
    <input type="submit" id="submit" value="Submit" />
</form>

The trouble I'm having is with the span at the bottom that says "Error!". I want this to show ONLY if one of the inputs is both "ng-dirty" and "ng-invalid". As it is above, the error will show until the form is completely valid. The long solution would be to do something like:

<span ng-show="submit_entry_form.first_name.$dirty && submit_entry_form.first_name.$invalid || submit_entry_form.last_name.$dirty && submit_entry_form.last_name.$invalid || submit_entry_form.email.$dirty && submit_entry_form.email.$invalid || submit_entry_form.confirm_email.$dirty && submit_entry_form.confirm_email.$invalid">Error!</span>

Which is UGLY. Any better way to do this?

like image 560
crunkchitis Avatar asked Jan 15 '13 21:01

crunkchitis


1 Answers

Method 1: Use a function on $scope set up by your controller.

So with a better understanding of your problem, you wanted to show a message if any field on your form was both $invalid and $dirty...

Add a controller method:

app.controller('MainCtrl', function($scope) {

  $scope.anyDirtyAndInvalid = function (form){
    for(var prop in form) {
      if(form.hasOwnProperty(prop)) {
         if(form[prop].$dirty && form[prop].$invalid) {
           return true;
         }
      }
    }
    return false;
  };
});

and in your HTML:

<span ng-show="anyDirtyAndInvalid(submit_entry_form);">Error!</span>

Here is a plunker to demo it

Now all of that said, if someone has entered data in your form, and it's not complete, the form itself is invalid. So I'm not sure this is the best usability. But it should work.


Method 2: Use a Filter! (recommended)

I now recommend a filter for this sort of thing...

The following filter does the same as the above, but it's better practice for Angular, IMO. Also a plunk.

app.filter('anyInvalidDirtyFields', function () {
  return function(form) {
    for(var prop in form) {
      if(form.hasOwnProperty(prop)) {
        if(form[prop].$invalid && form[prop].$dirty) {
          return true; 
        }
      }
    }
    return false;
  };
});
<span ng-show="submit_entry_form | anyInvalidDirtyFields">Error!</span>
like image 175
Ben Lesh Avatar answered Oct 02 '22 20:10

Ben Lesh