问题
i have a custom element directive e.g. like below
<my-wrapper ng-model="values.abc" unique-check="" list="list" prop="name"> </my-wrapper>
This directive does require ng-model which is later being set on the inner input tag
<input type="text" name="myfield" ng-model="'+attrs.ngModel+'"/>
the problem happening is when I check console I can see ng-model on directive is not same as ng-model on input tag.
How can I make sure that the ng-model on outer tag is not created and its created only once inside my directive.
my directive code is below
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
}
});
Please note that above is just a shortened version of my directive, and I have keep scope: true because of requirement in the overall scenario.
If its not clear what I am talking about, please checkout the console of THIS PLUNKER
I tried solutions with terminal : true
and/or priority : 1001
so that the ng-model is not created on the directive html but only on input tag, but none of them worked.
yes, one solution can be to replace ng-model with lets say my-model on the directive and then again add it as ng-model on input tag, but then its being used at almost 1000s of places in my app, so really wont like to replace it as such.
any other way to solve this problem.
回答1:
So try this plunker. Basically I made the my-wrapper
directive pass through its simple properties onto its input tag. For attributes that needed to be parsed, I simply parsed them and injected them into the scope create by the my-wrapper
directive.
I am not very sure why you have a directive that wraps a form around a single input, but like you said this is a contrived example. Personally I would change this structure, but I tried not to be too disruptive.
Hope this helps. Maybe you can explain your intent behind this.
回答2:
You could try using transclusion. Instead of trying to do the hard part of breaking through standard AngularJS compilation, you could just change your structure to something like:
<my-wrapper>
<input name="..." ng-model="...">
</my-wrapper>
and make your directive expand the wrapper into your template with transcluded input inside it. (See the transclude
option in $compile documentation.) This would increase readability of your templates as well.
Alternatively, if you need your directive to generate complex content (multiple inputs, etc.) all encapsulated and bound to that single ng-model
, you could leave the ng-model
where it is and make your directive completely encapsulated. By this I mean something like:
.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);
});
}
};
})
(see ngModelController documentation). You just need to be careful not to create an infinite loop between your $parser
and $formatter
.
If you're really dead set on leaving ng-model
on your wrapper and skipping it using priority
and terminal
, it's pretty simple:
.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*
}
};
}
This approach should be avoided if at all possible, because it has many apparent downsides and no real upside.
来源:https://stackoverflow.com/questions/27559982/stop-execution-of-other-directive-on-my-custom-element-directive