我有一个自定义元素指令,例如如下所示
<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个地方使用它,所以真的不喜欢这样替换它。
解决此问题的任何其他方式。
答案 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
留在您的包装上并使用priority
和terminal
跳过它,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*
}
};
}
如果可能的话,应该避免这种方法,因为它有许多明显的缺点,没有真正的好处。