ngModel needs $parent when within Transcluded html

佐手、 提交于 2019-12-13 04:47:24

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!