访问指令的隔离范围与嵌入的内容
Posted
技术标签:
【中文标题】访问指令的隔离范围与嵌入的内容【英文标题】:Access directive's isolate scope from within transcluded content 【发布时间】:2013-04-16 19:42:43 【问题描述】:我不确定这是否真的可行,但我本质上是想要 AngularJS 中的 '&' 隔离范围的反向。这是一个Plunkr 来演示。
基本上,我设置了一个自定义指令来提供一些可重用的 html。它利用ng-transclude
允许在其中呈现一些外部内容。但是,我发现了一种情况,我想从代码的嵌入部分访问已在指令的隔离范围上设置的函数。
所以基本上我有一些看起来像:
<div ng-controller="MainController">
<!-- The directive -->
<div some-custom-directive>
<!-- Button 1 that invokes a method within the controller scope -->
<button id="button1" ng-click="invoke1()">Invoke from Controller</button>
<!-- Button 2 that invokes a method on the isolate scope for the custom directive -->
<button id="button2" ng-click="invoke2()">Invoke from Isolate Scope</button>
</div>
</div>
有人知道这是否真的可能吗?
更新
根据@Mark Rajcok 的回答,$scope
上的$$prevSibling
可用于从嵌入内容中访问指令的隔离范围。但是,我已经更新了上面的 Plunkr 以从 ng-repeat
指令中尝试此操作,但该指令不起作用。我假设该重复中的项目不继承范围。
【问题讨论】:
【参考方案1】:这是一个解决您当前问题的解决方案。我不确定您要做什么。但据我所知,没有办法从外部范围调用隔离范围内的东西。当然,您可以在隔离作用域和外部作用域之间设置双向绑定变量,更改外部作用域中的变量并在隔离作用域上 $watch (这将像事件机制一样工作)......这是一个做你想做的事的方式..如果你坚持的话。
另外,有一种机制可以从隔离作用域调用外部作用域上的函数。有点像回调。
看到这个http://plnkr.co/edit/5MT4vo9qXtV6nQikfEiH?p=preview
【讨论】:
【参考方案2】:虽然可能,但我提出的解决方案是一个 hack,因为它使用范围内部变量 $$prevSibling
。
在您被嵌入的内容中,您处于被嵌入的范围内。该指令的隔离和嵌入范围是同级的。要从嵌入范围到隔离范围,可以使用$$prevSibling
。 (要从隔离作用域到转入作用域,可以使用$$nextSibling
。)
所以,这个 hack 会起作用:
<a href="" ng-click="$$prevSibling.action()">Invoke the Directive Action</a>
要在控制器范围内调用方法,您需要指定使用&
,正如@ganaraj 已经演示的那样:
<content-presenter controller-action="action()">
然后在你的指令中:
scope: controllerAction: '&' ,
template: ... +
'<button ng-click="controllerAction()">Trigger Ctrl action()</button>' ...
Plunker
使用 ng-repeat(请参阅 Samuel 的评论),每个项目都会创建嵌入范围的子范围。在下图中,我只显示了一个item
以保持图片更小。反转 $$prevSibling 的 $$nextSibling 棕色箭头。
因此,从 ng-repeat 子作用域到隔离作用域上定义的方法 action()
的技巧是
<div ng-repeat="item in items" ng-click="$parent.$$prevSibling.action()">
Angular v1.3+ 更新:
从 Angular v1.3 开始,transcluded 作用域现在是指令的isolate 作用域的子对象——它们不再是兄弟。所以要从嵌入范围到隔离范围,请使用$parent
。
使用 ng-repeat,每个项目仍然创建一个被嵌入范围的子范围:
但是要从 ng-repeat 子范围中访问在隔离范围上定义的方法 action()
,我们现在使用
<div ng-repeat="item in items" ng-click="$parent.$parent.action()">
【讨论】:
干杯,成功了。但是,我发现它在ng-repeat
中不起作用(我假设因为每个项目都没有从控制器继承$scope
。无论如何每个项目都可以访问$$prevSibling
?我已经更新了以上Plunkr举个例子。
太棒了,就像一个魅力!感谢您的图表,非常有用。
您知道是否可以在视图代码中为$parent
链定义一个有意义的名称?类似ng-let="isolateScope = $parent.$parent"
【参考方案3】:
据我了解,将ng-repeat
添加到元素会创建一个新范围,以便正确绑定重复内容。您可能需要在该链中添加一个 $parent
,例如 $parent.$$nextSibling
,以便升级到与指令的隔离范围相邻的级别。
【讨论】:
以上是关于访问指令的隔离范围与嵌入的内容的主要内容,如果未能解决你的问题,请参考以下文章
在 AngularJS 中从没有隔离范围的指令调用控制器函数