DonJuwe
DonJuwe

Reputation: 4563

How to access Angular form validation within a directive

I have a simple form with a directive:

<form name="testform">
    <input name="testfield" type="text" ng-model="test.name" ng-minlength="3" my-validate>
</form>

Since Angular validates the field itself when entering less than 3 characters, it sets testform.testfield.$invalid.

What I want to achieve is to add some custom validation functionality in a directive and react to this angular validation/set the validation result e.g. with the help of watchers or events like so:

angular.module('myApp.directives').directive('myValidate', [function() {
    return {
        link: function(scope, elem, attrs) {
            elem.on('keyup', function() {
                // do some custom validation
                // if valid, set elem to $valid
                // else set $error
                // something like elem.set('$valid');
            }
        }
    };
}]);

How can I achieve the combination of HTML5, Angular and custom form validation while using Angulars testform.testfield.$invalid, testform.testfield.$valid, testform.testfield.$error etc. logic?

Upvotes: 1

Views: 2385

Answers (2)

brianj
brianj

Reputation: 316

You can do custom validation and combine it with Angular's built in validation, you just need to require ngModel, pass ctrl as the 4th value to your link function, and use ctrl.$setValidity to indicate if your custom validation passes or fails.

The example below will be invalid if the length < 3 OR if the value is the string 'invalid':

var app = angular.module('app', []);

app.controller('controller', ['$scope',
  function(scope) {
    scope.test = {
      name: ''
    };
  }
]);

app.directive('myValidate', [
  function() {
    return {
      require: 'ngModel',
      link: function(scope, elem, attrs, ctrl) {
        ctrl.$parsers.unshift(function(value) {
          var valid = true;
          if (value === 'invalid') {
            valid = false;
          }
          ctrl.$setValidity(attrs.name, valid);
          return valid ? value : undefined;
        });
      }
    };
  }
]);

Markup:

<body ng-app="app">
    <div ng-controller="controller">
      <form name="testform">
        <input name="testform" type="text" ng-model="test.name" ng-minlength="3" my-validate /><br/>

      </form>
      <span style="color:green" ng-show="testform.testform.$valid">** valid **</span>
      <span style="color:red" ng-show="testform.testform.$invalid">** invalid **</span>
    </div>
    <script src="script.js"></script>
  </body>

Here is a plunker with this code: http://plnkr.co/edit/6XIKYvGwMSh1zpLRbbEm

The Angular documentation talks about this, though it wasn't totally obvious: https://docs.angularjs.org/api/ng/type/ngModel.NgModelController

This blog helped me get a hold on this: http://www.benlesh.com/2012/12/angular-js-custom-validation-via.html

Upvotes: 1

Gabriel
Gabriel

Reputation: 407

By default Angular provides some directives for input validation (like required, pattern, min, max etc.). If these directives doesn't suffice, custom validation is available. To be able to do that, the directive requires the model used for validation, then it can set the validity of the element like below:

.directive('myValidate', [ function() {
    return {
        require: 'ngModel',
        link: function(scope, elem, attrs, ctrl) {
            ctrl.$setValidity('myValidate', false);
        }
    };
}]);

A Plunker with such a directive which will become invalid when you enter '0' is HERE.

You can read more about custom validation on Angular forms documentation.

Upvotes: 2

Related Questions