在另一个指令中绑定指令的角度方式是什么?

时间:2013-05-24 18:57:08

标签: javascript angularjs angularjs-directive

我正在编写一个指令,用于在输入上建立客户端和服务器端验证。它应该接受一个验证器名称数组(例如aa-validate="required,unique"),循环它们,为所有可能的验证器添加客户端验证指令(例如required应该添加ngRequired),并且休息,发布到服务器端验证API。

最后一部分效果很好:我正在观看ngModel属性,并以100毫秒超时发布到服务器。但是,在我的指令的链接函数中设置客户端验证指令不会导致它们被编译和链接。换句话说,他们什么都不做。这是我的代码:

angular.module('form', [])
    .directive('aaValidate', ['$http', function($http) {
        return {
            priority: 1,
            restrict: 'A',
            require: 'ngModel',
            link: function(scope, element, attrs, ctrl) {
                var validate = attrs.aaValidate,
                    validators = validate.split(',');

                // This is the problem!
                //
                // Populate possible client-side validators
                for (var i = 0, len = validators.length; i < len; i++) {
                    var validator = validators[i];
                    switch (validator) {
                        case 'required':
                            attrs.$set('ngRequired', 'true'); break;
                        // ... and so on for ngPattern, etc.
                        default: break;
                    }
                }

                scope.$watch(attrs.ngModel, function(value) {
                    // This part works!
                    //
                    // Clear existing timeout, reset it with an
                    // $http.post to my validation API, the result is
                    // passed into ctrl.$setValidity
                });
            }
        }
    }]);

我确实尝试注入$compile,并在链接函数的末尾重新编译元素。我最终得到了无限的递归,可能是因为我没有删除一些属性,但即使我设法这样做,也感觉相当难看。什么是正确的方法?

非常感谢任何帮助。提前谢谢。


编辑: jsFiddle:http://jsfiddle.net/3nUdj/4/

1 个答案:

答案 0 :(得分:1)

我的第一个回答是错误的 - 我认为没有办法使用$compile服务。这是你如何在不获得无限递归的情况下完成的。我基本上将指令拆分为两个指令 - 一个添加验证指令,删除自身并重新编译。另一个做其他事情:

angular.module('form', [])
.directive('aaValidate', ['$http', '$compile', function ($http, $compile) {
  return {
    link: function (scope, element, attrs) {
      var validate = attrs.aaValidate,
          validators = validate.split(',');

      // Populate possible front-end validators
      for (var i = 0, len = validators.length; i < len; i++) {
        var validator = validators[i];
        switch (validator) {
          case 'required':
            attrs.$set('ngRequired', 'true');
            break;
          default:
            break;
        }
      }
      attrs.$set('aaOther', '');
      element.removeAttr('aa-validate');
      $compile(element)(scope);
    }
  }
}])

.directive('aaOther', function () {
    return {
      require: 'ngModel',
      link: function (scope, element, attrs, ctrl) {
        scope.$watch(attrs.ngModel, function (value) {
          // Server-side validation
        });
      }
    }
});

您必须重新编译链接元素才能在ng-repeat中工作。我已经更新了小提琴:http://jsfiddle.net/3nUdj/7/