隔离范围需要模板

时间:2014-09-25 20:38:01

标签: angularjs angularjs-scope

这是一个令人难以置信的简单应用程序:

<body ng-controller="MainCtrl">

    <div parent ng-repeat="parent in parents">
      <h1>{{ parent.family }} Family</h1>

      <div child="parent.child">
        Their kid's name is {{ child }}
      </div>
    </div>

</body>

使用以下app.js

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.parents = [{
      'child' : 'John',
      'family': 'Johnson'
    }, {
      'child' : 'Jack',
      'family': 'Jackson'
    }, {
      'child' : 'Jeff',
      'family': 'Jefferson'
    }];
});


app.directive('parent', function()
{
    return {
      restrict: 'AE'
    }
});

app.directive('child', function()
{
    return {
      restrict: 'AE',
      scope: {
        child: '='
      }
    }
});

我期待看到三排“杰克逊家族。他们孩子的名字是杰克”等等。但是,由于child上的隔离范围,这不起作用。相反,如果我将标记更改为

<div parent ng-repeat="parent in parents">
  <h1>{{ parent.family }} Family</h1>

  <div child="parent.child"></div>
</div>

然后在child指令template: 'Their kid\'s name is {{ child }}'添加额外的一行,然后就可以了。

以下是两种情景的关键词:

  1. FAULTY plunker
  2. WORKING plunker
  3. 为什么?

2 个答案:

答案 0 :(得分:2)

如果没有额外的工作,您可以在指令中使用transclude选项,以便内容绑定到父作用域,但内容必须是:

Their kid's name is {{ parent.child }}

或者,您可以隔离范围(如您所做),但是范围需要应用于指令中定义的模板 - 您不想这样做。

修改

下面的$compile - 方法(如最初编写的)是次优的,因为它会使内容编译和链接两次。正确(和更好)的方法是使用transclude

app.directive('child', function($compile)
{
    return {
      restrict: 'AE',
      transclude: true,
      scope: {
        child: '='
      },
      link: function(scope, elem, attrs, ctrls, transclude){
          transclude(scope, function(clone){
             elem.append(clone);
          });
      }
    }
});

已修改plunker

transclude在编译child指令时编译内容,但使编译的内容可用。通过调用transclude函数,您可以将内容链接到指定的范围 - 这里是子指令的范围。

原始答案(不推荐)

要使您的示例工作 - 即使用指令的内容作为模板 - 您需要使用指令的范围对它们进行编译,如下所示:

app.directive('child', function($compile)
{
    return {
      restrict: 'AE',
      scope: {
        child: '='
      },
      link: function(scope, elem){
          $compile(elem.contents())(scope));
      }
    }
});

这是您修改后的plunker

答案 1 :(得分:0)

在第二种情况下,你已经过了

 <div child="parent.child"></div>

您使用双向绑定将parent.child传递给指令

scope: {
        child: '='
      },

因此您可以在模板中使用子项

template: 'Their kid\'s name is {{ child }}'

在第一种情况下(有缺陷)你要重新招架孩子

Their kid's name is {{ child }}

但是孩子不存在你可以通过将其改为

来解决这个问题
 Their kid's name is {{ parent.child }}

请见http://plnkr.co/edit/V4ds0YHjGboQUlR3vzy6?p=preview