【问题标题】:AngularJS: Access directive's isolated scope from parent controllerAngularJS:访问指令与父控制器的隔离范围
【发布时间】:2013-01-29 10:04:59
【问题描述】:

我想编写一个具有隔离作用域的指令,但也想让该作用域可用于父作用域的控制器。我找到了这个解决方案:

<div ng-controller="Main">
  <popupbutton directive-scope="popup"></popupbutton>
</div>

app.directive('popupbutton', [function() {
  return {
    restrict:   "E",
    scope:      {    
      directiveScope: "="
    },
    link:       function(sc, el, attrs) {
      sc.directiveScope = sc;
      sc.testvalue = 'foo';
    }
  };  
}]);

app.controller('Main', function($scope) {
  alert($scope.popup.testvalue);  // Where did the property 'popup' come from?!?
});

Plunker

我觉得这有点难看,因为它涉及在 HTML 中编写一个属性,而在控制器的代码中,您无法分辨范围属性的来源。有没有更好的方法来做到这一点?

编辑:

此外,似乎 $scope.popup 在控制器“Main”运行时甚至都不可用。指令的链接功能还没有执行?

【问题讨论】:

  • 您根本不应该从控制器访问指令的范围。可能有更好的方法来做到这一点 - 你的用例是什么?
  • 指令创建一个按钮和一个可以通过单击按钮打开的弹出框。我希望父控制器查看盒子是否打开。该指令的范围还包含打开和关闭盒子的方法,父控制器也应该可以访问这些方法。

标签: angularjs


【解决方案1】:

为了保持适当的关注点分离,您不应该混合范围。更不用说它会很难同步。总结一下:你的指令不应该知道关于父作用域(或其控制器)的任何事情,你的控制器不应该知道关于指令内部的任何事情。它们是不同层中的独立组件。

在控制器和指令之间进行通信的正确方法是通过指令属性。例如,在弹出窗口的情况下,这可以通过一个简单的布尔值来完成。

控制器和指令:

app.directive('popupbutton', [function() {
  return {
    restrict: "E",
    scope: { isOpen: "=" },
    template: '<a ng-click="isOpen = !isOpen">Toggle</a><div>Open? {{isOpen}}'
  };
}]);

app.controller('MainCtrl', function($scope) {
  $scope.isOpen = false;
});

还有标记:

<popupbutton is-open="isOpen"></popupbutton>

此方法不需要逻辑,开箱即用,并保持关注点的清晰分离。这是一个更新的 plunker:http://plnkr.co/edit/otIaGCLmiNdGcYEgi60f?p=preview

【讨论】:

  • 谢谢!在你的帮助下,我编写了这个指令:plnkr.co/edit/vqkPBDkYT2zVVEGXBZVQ?p=preview。但是,如果我在 HTML 中省略了“is-open”属性,则会收到错误消息:“错误:不可分配的模型表达式:未定义(指令:popupbutton)”。我怎样才能使属性'is-open'可选?
  • 是的,为简单起见,我保持不变,而实际上您不会这样做。在现实世界中,该指令将有自己的内部变量来表示“真实状态”和一个带有 $watch 的单独属性,该属性将在真实状态发生变化时更新。我只是将它们合二为一,以使这里的功能更加清晰。
  • 我 fork 你的 plunker(见plnkr.co/edit/vh6yOigpHd7E5ijJ3QEa?p=preview)来探索我遇到的一个奇怪问题。如果我在我的指令标签内放置一个带有 ng-click 属性的标签(将“transclude”设置为 true),它将无法正常工作。左下角的按钮什么也不做,而右下角的按钮起作用。我不明白这两个按钮的原因或区别。
  • 这似乎违反直觉,但原因是范围继承。通过嵌入,内容在 child 范围内进行评估;即ng-clicks 在原型上继承自控制器范围的范围内。所以对象(包括函数)是对父作用域中值的引用,但原语(字符串、数字、布尔值)是副本。也就是说,它不再是相同的isOpenThis article 多讲这个,必读。
  • @Esa,我刚刚用一些图片更新了SO answer related to transcluded scope。 (Josh 提到的文章引用了这个答案,但它有点被埋没了,所以我认为直接指出它可能很有用。)
猜你喜欢
  • 2016-03-28
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 2015-12-08
  • 1970-01-01
  • 2013-08-06
相关资源
最近更新 更多