Narek Mamikonyan Narek Mamikonyan - 1 month ago 9
AngularJS Question

How to control form validity from other directives

My form is:

<form name="regForm" novalidate>

<div class="form-group has-feedback" form-validation>
<label class="control-label">Username</label>
<div ensure-unique="{{user.username}}">
<input type="text" class="form-control" name="username"
ng-model="user.username"
required
ng-minlength="3" />
</div>
</div>
</form>


In ensure-unique directive I'm checking if the username taken or not, and in that case if username used I want to set my username field to invalid.
How can I do that, if I don't want to apply ensure-unique directive to
<input>
element? Because I want to isolate scope of this directive and use
ng-transclude
. When I'm applying on input element the
ng-transclude
doesn't work.

Answer

You could require a parent form controller, then get the corresponding ngModel controller by input's name like formCtrl['username']:

return {
  restrict: 'A',
  scope: {
    isPending: '=',
  },
  require: '^form',
  link: function (scope, element, attrs, formCtrl) {
    var modelCtrl = formCtrl[attrs.ensureUnique];

    if (!modelCtrl) { return; }

    var counter = 0;
    scope.isPending = false;

    var validator = function (value) {
      modelCtrl.$setValidity('unique', false);
      scope.isPending = true;

      var currentCount = ++counter;

      checkUnique(value).then(function (isUnique) {
        if (currentCount !== counter) { return; }

        modelCtrl.$setValidity('unique', isUnique);
        scope.isPending = false;
      });

      return value;
    };

    modelCtrl.$parsers.push(validator);
    modelCtrl.$formatters.push(validator);
  }
};

Example: http://jsbin.com/cequp/18/edit