【问题标题】:AngularJS: can I use transcluded content in directive without redefining controller?AngularJS:我可以在指令中使用嵌入的内容而不重新定义控制器吗?
【发布时间】:2014-02-28 10:50:36
【问题描述】:

我有一个选项卡控件,它可以根据所选选项卡显示或隐藏控件中的内容。

这很好用,但是选项卡窗格的内容开始与范围出现奇怪的行为。引用嵌入内容中的范围似乎不再引用定义的控制器范围。

这可以在任何包含嵌入内容的指令中看到。给定特定的控制器:

app.controller("MainCtrl", function ($scope) {
  $scope.getTestText = function () {
    alert($scope.testText);
    alert(this.testText);
  }
});

在以下标记中使用:

<h1>Outside Tab</h1>
<div>
    <input type="text" ng-model="testText" />
    <button ng-click="testText = 'outside'">Set Test Text</button>
    <button ng-click="getTestText()">Get Test Text</button>
    {{testText}}
</div>

<simple-directive>
  <h1>Inside Directive</h1>
  <div>
      <input type="text" ng-model="testText" />
      <button ng-click="testText = 'inside'">Set Test Text</button>
      <button ng-click="getTestText()">Get Test Text</button>
      {{testText}}
  </div>
</simple-directive>

this plunker

如果单击顶部的“设置测试文本”按钮,然后单击“获取测试文本”按钮,两个警报会显示相同的内容(“外部”)。如果您单击第二个“设置测试文本”按钮,然后单击“获取测试文本”,则会出现不同的结果:尽管“this”具有预期的“内部”值,但范围上的值仍然是“外部”。

一种解决方法是在嵌入的内容中定义控制器,如下所示:

<simple-directive>
  <h1>Inside Directive</h1>
  <div ng-controller="MainCtrl">
      <input type="text" ng-model="testText" />
      <button ng-click="testText = 'inside'">Set Test Text</button>
      <button ng-click="getTestText()">Get Test Text</button>
      {{testText}}
  </div>
</simple-directive>

但如果可能的话,我宁愿避免这种情况。

所以我的问题是:有没有更好的方法来不改变范围?这只是预期的行为吗?

【问题讨论】:

    标签: angularjs angularjs-directive


    【解决方案1】:

    ngTransclude 创建一个子(非隔离)作用域:

    $transclude 函数默认创建一个新的子作用域source code

    transcludedScope = scope.$new();
    

    最好的解决办法是避免在作用域上引用原语:

    为什么不使用原语?看到类似的答案...

    一个演示插件:http://plnkr.co/edit/LuU6ard1JYsYCOvlP5iY?p=preview

    app.controller("MainCtrl", function ($scope) {
      $scope.test = {};
      $scope.getTestText = function () {
        alert($scope.test.text);
        alert(this.test.text);
      }
    });
    

    模板:

    <input type="text" ng-model="test.text" />
    <button ng-click="test.text = 'inside'">Set Test Text</button>
    <button ng-click="getTestText()">Get Test Text</button>
    {{test.text}}
    

    另一种解决方案是手动转置而不创建新的子范围:

    app.directive('simpleDirective', function () {
        return {
            restrict: 'E',
            replace: true,
            transclude: true,
            scope: {},
            link: function(scope,elm,attrs,ctrl,$transclude){
              $transclude(scope.$parent, function(clone){
                elm.after(clone);
              })
            }
        };
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-16
      • 1970-01-01
      • 1970-01-01
      • 2014-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多