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

时间:2015-03-03 17:26:53

标签: angularjs angularjs-directive angularjs-scope

为了说明我想要实现的目标,我将提供一份不完整的信息 accordion widget:http://plnkr.co/edit/aiUKTRmRk5qFqPKCy2Md?p=preview

我有2个手风琴窗格指令,坐在我的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>

和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
    };
  }]);

这些窗格已经转换为:true,因此我在html中添加的内容得到了 包裹在他们的模板中。

每个窗格还必须包含一个accordion-header指令 指令,使用范围变量在折叠或显示中显示自身 扩大的国家。

问题,你可以在这个问题上看到,我无法孤立 范围正确。

默认行为是两个窗格共享相同的范围,因此 当我扩展一个时,它们都会扩展。

如果我尝试在accordion-pane指令上隔离范围 (通过取消注释范围:{}行在script.js中),然后是范围 手风琴窗格不会被转换成手风琴标题的孩子。

在我看来,这似乎是一种排列事物的合理方式,但显然我是 错误。关于如何实现这一点的任何想法,以及为什么要孤立 父母的范围,使其对孩子不可用?

编辑:正如肖恩在gitter上指出的那样:

“Per angular docs:

“transclude选项改变了嵌套范围的方式。它使得transcluded指令的内容具有指令之外的任何范围,而不是内部的任何范围。这样做,它给出了内容访问外部范围。“”

这很合理,但是......我如何隔离范围并同时使用ngTransclude?

编辑2:

Jim的建议在plunkr中表现得非常好。所以我用更复杂的例子更新了plnkr:http://plnkr.co/edit/sbiSF8OQ2Ang99Z0OaHB?p=preview

这里的问题是,范围似乎与手风琴窗格相隔离,但相反,它在儿童兄弟姐妹中是孤立的。

因此,通过将toggle函数移动到accordion-header,accordion-header和accordion-body可以访问该范围,但是accordion-pane(他们的父级)没有访问权限。

我在这里想要实现的目的是将手风琴窗格下的范围隔离开来,并在accordion-pane,accordion-body和accordion-header之间共享该范围。目前,范围仅在accordion-body和accordion-header之间共享。

2 个答案:

答案 0 :(得分:2)

为什么指令上的隔离范围导致转换中断,我不确定。

但是,就简单地使用您设置的模板找到解决方案而言。添加ng-if =&#34; 1&#34;每个手风琴窗格元素。

ng-if documentation

  

请注意,使用ngIf 删除元素时,其范围将被销毁,并且在元素恢复时会创建新范围。在ngIf中创建的作用域使用原型继承继承其父作用域

因此,通过向元素添加ng-if="1"属性/指令,您将隔离范围,因此$scope.active对每个元素都是唯一的。

您可以查看此修订后的Plunker Example

答案 1 :(得分:1)

看起来您的问题不在于确定范围,而是在您进行切换的位置。这将逐个展开和折叠每个窗格(从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;
        };
      }
    };
  }]);

如果你愿意的话,我会找出一个折叠他人的例子。