WBC
WBC

Reputation: 1904

Proper way to display form validation errors in Angular?

I display alerts at the top of the page if a validation error is triggered, the current implementation also hides the error as soon as the error is fixed. It all works but seems inefficient, is there a better way?

HTML:

<div class="alert alert-danger"
  ng-repeat error in advAlerts
  ng-show="error.hasError()">
  {{error.text}}
</div>

JS:

$scope.advAlerts = [
  {
    hasError: checkFooError,
    text: 'Error Foo',
  },
  {
    hasError: checkBarError,
    text: 'Error Bar',
  },
  ...
]   

function checkFooError() {
  //check a list of required attributes to see they're all filled out
  //returns true/false
}

With this method, the page is responsive: after clicking submit, if any required attributes are missing, the alert displays. When all the required attributes are filled out, the alert instantly goes away.

However, the checkFooError function gets called a ton due to the digest cycle (I think?), is there a better way to do this?

-EDIT-

The standard validation things are already in place, I forgot to mention these are "advanced alerts" because they're something extra the designers wanted.

Upvotes: 0

Views: 803

Answers (2)

guilhebl
guilhebl

Reputation: 8990

If you want to avoid boiler-plate obtrusive code in your html you can avoid placing all those ng-show and things like that in your form totally decoupling it from the validation mechanism itself.

You don't need to necessarily be tied to angular when performing validation in the client side, you can combine angularjs with any other JS framework and make them work together as independent modules with requireJS. I've been using bootstrapValidator together with angular, binding them with requireJS, and it performs well, giving you a clean code in your html, with totally decoupled modules , you can attach a listener when your view is loaded using $viewContentLoaded , then you enable validation on your form using a function call, I'm posting a sample code as an example:

  1. a clean angularJS form:

      <form id="myForm" novalidate="novalidate" class="form-horizontal">            
            <label>name</label> 
            <input type="text" class="form-control" id="name" name="name" ng-model="rec.name" />
    
            <label>description</label>
            <textarea rows="5" id="description" ng-model="rec.description" name="description">         </textarea>
    
    
        // ... more fields
    

in your controller code:

controllers.controller('MyCtrl', ['$scope', 'MyService',
  function($scope, MyService) {
    // ... controller code

    // setup validator based on your page form
    $scope.$on('$viewContentLoaded', loadFormValidator);        
  }]);

function loadFormValidator(){
    $('#myForm').bootstrapValidator({
        message: 'The form has invalid inputs',
        fields: {
            name: {
                message: 'The name is not valid',
                validators: {
                    notEmpty: {
                        message: 'The name is required and can\'t be empty'
                    },
                    stringLength: {
                        min: 6,
                        max: 70,
                        message: 'The name must be more than 6 and less than 70 characters long'
                    },
                    regexp: {
                        regexp: /^[a-zA-Z0-9_\.\s]+$/,
                        message: 'The name can only consist of alphabetical, number, dot, spaces and underscore'
                    }
                }
            },

            description: {
                message: 'The description is not valid',
                validators: {
                    notEmpty: {
                        message: 'The description is required and can\'t be empty'
                    },
                    stringLength: {
                        min: 6,
                        max: 160,
                        message: 'The description must be more than 6 and less than 160 characters long'
                    }
                }
            },
            price: {
                message: 'The price is not valid',
                validators: {
                    notEmpty: {
                        message: 'The price is required and can\'t be empty'                
                    },                  
                    regexp: {
                        regexp: /^\d+(,\d{1,2})?$/,
                        message: 'The price can only consist of digits or , to indicate fraction values'
                    }
                }
            }
    });
};

function isFormValid(){

    // Get plugin instance
    var bootstrapValidator = $('#myForm').data('bootstrapValidator');

    bootstrapValidator.validate();

    // validate and then call method is Valid to check results
    return  bootstrapValidator.isValid();
};

you might encapsulate the above code in a requireJS module or in a JS namespace or even inside a angular service. In your controller you can call "isFormValid" to check if all inputs are correct for that specific form:

/* callback for ng-click on your controller: */
$scope.saveRecord = function () {
  // validate fields
  if (isFormValid()) {
      MyService.save($scope.record);
      // ...
  }    
};

Upvotes: 1

helloworld
helloworld

Reputation: 965

Well, you don't have to code much for form validations in AngularJS. AngularJS provides us several properties which can use to check the form status. So you can check the status of the for and its controllers in various aspects.

Form statuses:-

$valid : Validates whether the form matchs the defined rules in html controls

$invalid : Validates whether the form is invalid according to defined rules

$pristine : True if the HTML control/tag has not been used by user

$dirty : True if the HTML control/tag has been used by user

example usage:-

<div class="form-group" ng-class="{ 'has-error' : yourForm.username.$invalid && !yourForm.username.$pristine }">
    <label>Username</label>
    <input type="text" name="username" class="form-control" ng-model="user.username" ng-minlength="3" ng-maxlength="8" required>
    <p ng-show="yourForm.username.$error.required">Username is short.</p>
    <p ng-show="yourForm.username.$error.minlength">Username is short.</p>
    <p ng-show="yourForm.username.$error.maxlength">Username is long.</p>
</div>

<div class="form-group" ng-class="{ 'has-error' : yourForm.email.$invalid && !yourForm.email.$pristine }">
    <label>Email</label>
    <input type="email" name="email" class="form-control" ng-model="user.email">
    <p ng-show="yourForm.email.$invalid && !yourForm.email.$pristine" >Enter a valid email.</p>
</div>

reference: Angular documentation for forms

Upvotes: 2

Related Questions