简体   繁体   English

AngularJS:在transclude设置为true的指令中隔离范围

[英]AngularJS : Isolating scope in a directive with transclude set to true

To illustrate what i'm trying to achieve, I will provide an incomplete accordion widget : http://plnkr.co/edit/aiUKTRmRk5qFqPKCy2Md?p=preview 为了说明我想要实现的目标,我将提供一个不完整的手风琴小部件: http//plnkr.co/edit/aiUKTRmRk5qFqPKCy2Md?p = preview

I have 2 accordion-pane directives, sitting next to eachother in my HTML. 我有两个手风琴窗格指令,坐在我的HTML旁边。

    <accordion-pane>
      <accordion-header>
        <h3>Pane 1</h3>
      </accordion-header>
    </accordion-pane>

    <accordion-pane>
      <accordion-header>
        <h3>Pane 2</h3>
      </accordion-header>
    </accordion-pane>

and the angular/js code : 和angular / js代码:

  .directive('accordionPane', [function () {
    return {
      transclude: true, 
      replace: true,
      //scope: {}, // Isolating the scope breaks transclusion
      templateUrl: 'accordion-pane.html',
      link: function (scope) {
        scope.toggle = function () {
          scope.active = !scope.active;
        };
      }
    };
  }])
  .directive('accordionHeader', [function () {
    return {
      templateUrl: 'accordion-header.html',
      transclude: true,
      replace: true
    };
  }]);

These panes have transclude: true, so that what I add in my html, gets wrapped in their templates. 这些窗格已经转换为:true,因此我在html中添加的内容将包含在他们的模板中。

Each pane must also contain an accordion-header directive, and this directive, uses a scope variable to display itself in a collapsed or expanded state. 每个窗格还必须包含accordion-header指令,并且此指令使用范围变量以折叠或展开状态显示自身。

The problem, as you can see in this plunker is that, I cannot isolate the scope properly. 正如你在这个问题上看到的那个问题是,我无法正确隔离范围。

The default behaviour is that both panes share the same scope, so when I expand one, they both expand. 默认行为是两个窗格共享相同的范围,因此当我展开一个窗格时,它们都会扩展。

If I try to isolate the scope on the accordion-pane directive ( by uncommenting the scope: {} line in script.js ), then the scope of accordion-pane isn't transcluded down into it's accordion-header child. 如果我尝试在accordion-pane指令上隔离范围(通过取消注释script.js中的范围:{}行),那么accordion-pane的范围不会被转换为它的accordion-header子节点。

This seems to me like a logical way of aranging things, but obviously I'm wrong. 在我看来,这似乎是一种排列事物的逻辑方式,但显然我错了。 Any thoughts on how this could be achieved, and why isolating the scope on the parent, makes it unavaiable to the child ? 关于如何实现这一目标的任何想法,以及为什么隔离父母的范围,使得它对孩子不可行?

Edit: As Sean pointed out on gitter : 编辑:正如肖恩指出的那样:

"Per angular docs: “每角度文档:

"The transclude option changes the way scopes are nested. It makes it so that the contents of a transcluded directive have whatever scope is outside the directive, rather than whatever scope is on the inside. In doing so, it gives the contents access to the outside scope."" “transclude选项改变了嵌套范围的方式。它使得transcluded指令的内容具有指令之外的任何范围,而不是内部的任何范围。这样做,它使内容访问到外部范围。“”

This makes sense ok, but ... How can I isolate scope and use ngTransclude at the same time ? 这是有道理的,但是......我如何隔离范围并同时使用ngTransclude?

Edit 2: 编辑2:

Jim's suggestion worked really well in the plunkr. Jim的建议在plunkr中表现得非常好。 So I have updated the plnkr, with a more complex example : http://plnkr.co/edit/sbiSF8OQ2Ang99Z0OaHB?p=preview 所以我更新了plnkr,有一个更复杂的例子: http ://plnkr.co/edit/sbiSF8OQ2Ang99Z0OaHB?p=preview

The problem here is that, the scope doesn't seem to be isolated from the accordion-pane down, but instead, it's isolated amongst the child siblings. 这里的问题是,范围似乎并没有与手风琴窗格隔离,而是在儿童兄弟姐妹中孤立。

So by moving the toggle function onto the accordion-header, accordion-header and accordion-body can access that scope, but accordion-pane ( their parent ), does not have access. 因此,通过将toggle函数移动到accordion-header,accordion-header和accordion-body可以访问该范围,但是accordion-pane(它们的父级)没有访问权限。

Once again what I'm trying to achieve here is to isolate the scope underneath the accordion-pane, and have that scope shared amongst accordion-pane, accordion-body and accordion-header. 我在这里想要实现的另一个目的是隔离手风琴窗格下面的范围,并在accordion-pane,accordion-body和accordion-header之间共享该范围。 Currently the scope is only shared between accordion-body and accordion-header. 目前,范围仅在accordion-body和accordion-header之间共享。

Why the isolated scope on the directive causes transclude to break, I am not sure. 为什么指令上的孤立范围会导致转换中断,我不确定。

But, in terms of finding a solution simply using the template you have setup. 但是,就简单地使用您设置的模板找到解决方案而言。 Add ng-if="1" to each accordion pane element. 为每个折叠窗格元素添加ng-if =“1”。

Per ng-if documentation : Per ng-if文档

Note that when an element is removed using ngIf its scope is destroyed and a new scope is created when the element is restored . 请注意,使用ngIf删除元素时, 其范围将被销毁,并且在还原元素时会创建新范围 The scope created within ngIf inherits from its parent scope using prototypal inheritance 在ngIf中创建的作用域使用原型继承从其父作用域继承

Therefore by adding that ng-if="1" attribute/directive to the element, you are isolating the scope and therefore $scope.active will be unique to each element. 因此,通过向元素添加ng-if="1"属性/指令,您将隔离范围,因此$scope.active对每个元素都是唯一的。

You can look at this revised Plunker Example : 你可以看看这个修订过的Plunker示例

It looks like your issue isn't with scoping, it's with where you've put the toggle. 看起来你的问题不在于范围界定,而在于你在哪里进行切换。 This will expand and collapse each pane individually (move toggle from accordionPane to accordionHeader link function): 这将单独展开和折叠每个窗格(从accordionPane切换到accordionHeader链接功能):

angular.module('accordion-test', [])
  .directive('accordionPane', [function () {
    return {
      transclude: true, 
      replace: true,
      //scope: {}, // Isolating the scope breaks transclusion
      templateUrl: 'accordion-pane.html'
    };
  }])
  .directive('accordionHeader', [function () {
    return {
      templateUrl: 'accordion-header.html',
      transclude: true,
      replace: true,
      link: function(scope,elem,attr,ctrl){
        scope.toggle = function () {
          scope.active = !scope.active;
        };
      }
    };
  }]);

I'll work out an example for collapsing others if you'd like. 如果你愿意,我会找出一个折叠他人的例子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM