Building complex validation rules with angularjs

Oscar Brito

It was late and there was bug on a web form that I was building. It seems that was performing a post without a required value. In other words, client-side validation was incomplete.

Forms are the most complicated software that you'll ever need to write. It gets worst when you're doing fullstack and you need to handle validation, security, design, backend support, ... and a million other things.

This post describes how to do a multiple checkbox required validation using angular directives.

Validation Directive

This example implements the required validation for multiple selection checkboxes. The validation is done via a angular directive that is associated with the form. We also can build complex validation rules by accessing the $scope fields and using $setValidity to set error messages, ...

Please note that this is just an example which intends to just describe the steps to build a complex validation using angular.

The example contains code for the HTML, angular controller and angular directive.

HTML

An example of a multiple selection checkbox binding.

<form name="bookingForm"  
      method="POST" 
      validation-selecteddays>

         <input  type="checkbox"
                id="selectedDays"
                name="selectedDays"
                model="selectedDays[0]">

         <input  type="checkbox"
                id="selectedDays"
                name="selectedDays"
                model="selectedDays[1]">

       ...

</form>

Controller

An example of a multiple selection checkbox binding data.

"use strict";

module.exports = function($scope){

    $scope.selectedDays = [false, false, false, false, false, false, false]    
    ...

}

Directive

An example of the validation-selecteddays directive that sets the form valid state using complex logic.

"use strict";

var _ = require("lodash");

module.exports = function() {  
    return {

        restrict: 'A',
        link: function(scope) {

            scope.$watchCollection(
                "selectedDays", 
                function(value) {

                    /// isValid if it has any true value on the list
                    var isValid = !!_.filter(value, function(val){ return !!val; }).length;

                    /// set the scope field as invalid                    scope.bookingForm.selectedDays.$setValidity("required", isValid);

                }, true);

        }
    };
};

Conclusion

By using this method you can created reusable validation logic that is decoupled from the angular controller and quickly enabled and disabled on your markup.

Angular version 1.4.X was used on this example.

Let me know your thoughts by sharing or commenting.

Oscar out.