Vivek Jha
Vivek Jha

Reputation: 1580

Form Input Field Validation Using Directives

I want to apply "ng-pattern" to the form input fields using a directive. Let's say I want to check if the value provided is an integer or not.

form-markup

<form class="form" name="frm" novalidate>
<div class="form-group">
    <label class="control-label">Age</label>
    <input int
        type="text"
        name="age"
        class="form-control"
        ng-model="fd.age">
        <span class="help-block" ng-show="frm.age.$error.pattern">
           age is just a number.
        </span>
</div>
</form>

and the directive code is like this

app.directive("int", function($compile){
    return {
        restrict: "A",
        scope: true,
        replace: true,
        link: function(scope, elem, attrs) {
            elem.attr("ng-pattern", "/[0-9]+/");
        }
    }
});

In the markup I can see that it is applied properly but still it doesn't work. The pattern is correct because when I use it explicitly in the markup without using the directive it works nicely.

I have two questions.

  1. Why this doesn't work?

  2. Since I have to write a lot of such domain specific directives, is my approach correct to solve this problem pattern.

Upvotes: 0

Views: 1077

Answers (1)

Max Novich
Max Novich

Reputation: 1169

Instead of trying to incapsulate an existing validator in your custom directive, you should try implementing a custom validation rule as explained in this article

I've modified your example using this technique.

Fiddle

Code:

<form class="form" name="frm" novalidate>
<div class="form-group">
    <label class="control-label">Age</label>
    <input int
        type="text"
        name="age"
        class="form-control"
        ng-model="fd.age">
        <span class="help-block" ng-show="frm.age.$error.numberValidator">
           age is just a number.
        </span>
</div>
</form>

JS:

app.directive("int", function() {
      return {
        restrict: "A",
        scope: true,
        replace: true,
          require: 'ngModel',
        link: function(scope, elem, attrs,ctrl) {
            function customValidator(ngModelValue) {
    
              if (/^[0-9]+$/.test(ngModelValue)) {
                ctrl.$setValidity('numberValidator', true);
              } else {
                ctrl.$setValidity('numberValidator', false);
              }
              return ngModelValue;
            }
            ctrl.$parsers.push(customValidator);
          }
        }
    });

Update

For your specific case - there is a standard validation rule $error.number described in this documentation

Update 2

To answer your first question - for the ng-pattern directive to be functional you need to re-run the compile cycle via $compile service for the given element and bind it to the scope. Like this:

myApp.directive("int2", function($compile) {
  return {
    restrict: "A",
    scope: true,
    replace: true,
    require: 'ngModel',
    link: function(scope, elem, attrs) {
      elem.attr("ng-pattern", "/^[0-9]+$/");
      elem.removeAttr("int2");
      $compile(elem)(scope); 
    }
  }
});

Here is an updated Fiddle to illustrate the behavior.

Upvotes: 1

Related Questions