Search code examples
angularjsangularjs-directiveangular-uiui-validate

Use ui-validate inside a directive template


It´s possible to use ui-validate inside a directive template like plunker example?

Plunker: http://plnkr.co/edit/H6v6nVobIM3EKmAVHZHa?p=preview

template.html

<div class="form-group" ng-class="{'has-error' : !isValid()}">
  <label for="{{name}}" class="control-label">{{label}}</label>
  <div class="input-group">
    <span class="input-group-addon">US$</span>
    <input type="number" 
      ng-model="ngModel" 
      ng-required="isRequired" 
      ui-validate="'$value > 0'" 
      class="form-control" 
      name="{{name}}" 
      id="{{name}}" 
    />
  </div>
</div>

script.js

.directive('currency', function() {
  return {
    restrict    : 'E',
    replace     : true,
    transclude  : true,
    require     : 'ngModel',
    scope       : { ngModel: '=' },
    templateUrl : 'template.html',
    link        : function(scope, elm, attr, ctrl) {

      scope.name = (attr.name || 'undefinedName');
      scope.label = (attr.label || 'undefinedLabel');
      scope.isRequired = (attr.required !== undefined);

      scope.isValid = function() {
        return ctrl.$valid;
      };
    }
  };
});

Usage:

<currency ng-model="foo.value" name="value" label="Value:" required></currency>

Solution

  • By Sander Elias:

    ngModel is very powerful, but it's also very picky on its surroundings. Due to the transclude and the isolate scope, ngModel does not register itself in the form. but for ui-validate, it is enough to get the ng-controller itself.

    To resolve basically just remove from directive the:

    require : 'ngModel'
    

    and make:

    var ctrl = elm.find('input').data('$ngModelController');
    

    A complete discussion can be seen at:

    https://groups.google.com/forum/#!topic/angular/cMgxWTM-j00