停止在我的自定义元素指令上执行其他指令

时间:2014-12-19 05:00:35

标签: angularjs angularjs-directive

我有一个自定义元素指令,例如如下所示

  <my-wrapper ng-model="values.abc" unique-check="" list="list" prop="name"> </my-wrapper>

该指令确实需要ng-model,后来在内部输入标记

上设置
  <input type="text" name="myfield" ng-model="'+attrs.ngModel+'"/>

发生的问题是当我检查控制台时我可以看到ng-model on指令与输入标签上的ng-model不同。

如何确保外部标记上的ng-model未创建,并且只在我的指令中创建一次。

我的指令代码在

下面
app.directive("myWrapper", function(){

  var templateFn = function(element, attrs){
    return '<div ng-form="myform">'+
          '<input type="text" name="myfield" ng-model="'+attrs.ngModel+'"/>'+
          '<span>(inside directive) : isDuplicate:{{myform.myfield.$error.isDuplicate}}</span>'
          '</div>';
  }

  return {
    restrict :'E',
    template : templateFn,
    require: 'ngModel',
    scope: true
  }
});

请注意,上面只是我的指令的缩短版本,并且由于整体方案的要求,我保留范围:true。

如果不清楚我在说什么,请查看THIS PLUNKER

的控制台

我尝试使用terminal : true和/或priority : 1001的解决方案,以便不在指令html上创建ng-model,而只在输入标记上创建,但没有一个工作。

是的,一个解决方案可以用指令上的my-model替换ng-model,然后再将它作为ng-model添加到输入标签上,但随后在我的应用程序的几乎1000个地方使用它,所以真的不喜欢这样替换它。

解决此问题的任何其他方式。

2 个答案:

答案 0 :(得分:1)

所以try this plunker。基本上我将my-wrapper指令通过其简单属性传递到其输入标记。对于需要解析的属性,我只需解析它们并将它们注入my-wrapper指令创建的范围。

我不太清楚为什么你有一个指令围绕一个输入包装一个表单,但就像你说这是一个人为的例子。就个人而言,我会改变这种结构,但我尽量不要过于具有破坏性。

希望这会有所帮助。也许你可以解释一下这背后的意图。

答案 1 :(得分:1)

您可以尝试使用翻译。您可以将结构更改为:

,而不是试图突破标准的AngularJS编译。
<my-wrapper>
    <input name="..." ng-model="...">
</my-wrapper>

并使你的指令将包装器展开到你的模板中,并在其中包含transcluded输入。 (请参阅$compile documentation中的transclude选项。)这样可以提高模板的可读性。


或者,如果你需要你的指令来生成所有封装并绑定到单个ng-model的复杂内容(多个输入等),你可以将ng-model保留在原来的位置并制定你的指令完全封装。我的意思是:

.directive('myComplexField', function () {
    return {
        scope: {},
        require: 'ngModel',
        link: function ($scope, $element, $attrs, ngModelCtrl) {
            ngModelCtrl.$formatters.push(function (modelValue) {
                // ... (update your isolated model based on external model change)
            });
            ngModelCtrl.$parsers.push(function (viewValue) {
                // ... (update external model based on your isolated model)
            });
            $scope.$watch('... (properties of your isolated model)', function () {
                // force sync (parser code above will take care of setting the real value)
                ngModelCtrl.$setViewValue(!ngModelCtrl.$viewValue);
            });
        }
    };
})

(见ngModelController documentation)。您只需要注意不要在$parser$formatter之间创建无限循环。


如果您真的死了,请将ng-model留在您的包装上并使用priorityterminal跳过它,pretty simple:< / p>

.directive('foo', function ($compile, $timeout) {
    return {
        restrict: 'E',
        priority: 2,  // ngModel priority is 1 (see the docs)
        terminal: true,
        link: function ($scope, $element) {
            $compile($element, undefined, 1)($scope);  // compiles priority *lower than 1*
        }
    };
}

如果可能的话,应该避免这种方法,因为它有许多明显的缺点,没有真正的好处。