【问题标题】:ngModel needs $parent when within Transcluded htmlngModel 在 Transcluded html 中需要 $parent
【发布时间】:2015-03-17 19:42:23
【问题描述】:

我有一个用于输入字段的指令,该指令使用嵌入来获取包含在指令元素中的元素,该元素包含ng-model 属性。在阅读了无数 SO 问题和 Angular 文档以了解如何让嵌入的 html 中的 ng-model 与我的指令中的 ng-model 同步后,我终于偶然发现了一个让它工作的技巧。那就是使用$parent,其中ng-model 在输入字段内。这一切都很好而且很花哨,但是,它看起来很笨拙/笨拙。

此处显示的 Plunker: http://plnkr.co/edit/gEje6Z2uuTs9DFPeCZfv

我试图通过在我的链接函数中搞乱嵌入函数来使它更优雅一点,如下所示:

```

      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);


      });

```

此外,在此 Plunker 中显示: http://plnkr.co/edit/11k9LiA5hyi4xydWBo3H?p=preview

有人会认为嵌入函数允许您使用指令的范围覆盖嵌入范围,然后ng-model 属性将关联并绑定到指令范围,但事实并非如此。

虽然$parent.<ng-model> 确实有效,但它看起来很hackish,并且可能导致错误,例如如果我的指令未与未定义account 对象的父作用域一起使用。

【问题讨论】:

    标签: angularjs angularjs-directive angular-ngmodel angularjs-ng-transclude


    【解决方案1】:

    有几种方法可以做到这一点。

    1) 使用= 公开account 变量

    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) 使用transclude函数:

    这类似于ngIfngRepeat 所做的。 ngRepeat 实际上用$index 和类似的值装饰每个作用域,就像你想用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>
    

    【讨论】:

    • 非常感谢您的详尽解释。我想知道为什么您不能使用隔离范围然后将该范围分配给 transclude 函数。有人会认为最初在 html 中定义并分配给父范围的 ng-model=account 然后将分配给指令的隔离范围。当您想完全使用 brand new untouched 范围时,这可能很有用。
    • 您可以致电transclude(scope.$new(true), function (...) {...})
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-25
    • 1970-01-01
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多