问题
I have a directive for a input field that uses transclusion to take the elements that are enclosed in the directives element which includes an ng-model
attribute. After reading countless SO questions and Angular documentation to find out how to get the ng-model
in the transcluded html to sync with the ng-model
in my directive I finally stumbled stumbled upon a trick to get it to work. That is to use $parent
where the ng-model
is within the input field. This is all fine and dandy, however, it seems clunky/hackish.
Plunker shown here: http://plnkr.co/edit/gEje6Z2uuTs9DFPeCZfv
I tried to make this a little more elegant by messing around with the transclusion function within my link function like so:
```
var transcludedContent, transclusionScope;
transcludeFn(scope, function(clone, scope) {
//headerCtrl.$element.append(clone);
transcludedContent = clone;
transclusionScope = scope;
console.log('scope form: ', scope);
console.log('transclude form: ', clone);
});
```
Also, shown in this Plunker: http://plnkr.co/edit/11k9LiA5hyi4xydWBo3H?p=preview
One would think that the transclusion function would allow you to overwrite the transclusion scope with the scope of your directive then the ng-model
attributes would be associated and bound to the directives scope, however, this is not the case.
Although, the $parent.<ng-model>
does work, it seems very hackish, and can lead to bugs like if my directive was not used with a parent scope that doesnt have an account
object defined.
回答1:
There are a couple ways of doing that.
1) Exposing the account
variable using =
http://plnkr.co/edit/DxsipWRj0AJe6Yi3bhse
JS:
app.directive('formControl', [function(){
return {
restrict: 'EA',
template: '<div ng-transclude></div>{{account.name}}',
scope: {
account: '='
},
transclude: true,
link: function(scope, element, attrs){
scope.account={};
console.log('SCOPE: ', scope)
}
};
}]);
HTML:
<form-control account='account'>
<label for="name">Enter Name:</label>
<input name="name" ng-model="account.name" \>
</form-control>
2) Using transclude
function:
This is similar to what ngIf
and ngRepeat
do. ngRepeat
actually decorates every scope with $index
and similar values, the same way you want to decorate your scope with account
.
http://plnkr.co/edit/cZjWqIgO23nzc0kMZA57
JS:
app.directive('formControl', ['$animate', function($animate){
return {
restrict: 'EA',
transclude: 'element',
link: function(scope, element, attrs, ctrl, transclude){
//this creates a new scope that inherits from the parent scope
//that new scope will be what you'll be working with inside your
//transcluded html
transclude(function (clone, scope) {
scope.account = {name:'foobar'};
$animate.enter(clone, null, element);
console.log('SCOPE: ', scope)
});
}
};
}]);
HTML:
<form-control>
<label for="name">Enter Name:</label>
<input name="name" ng-model="account.name" \><br>
{{account.name}}
</form-control>
来源:https://stackoverflow.com/questions/29108259/ngmodel-needs-parent-when-within-transcluded-html