从另一个指令触发指令

Triggering directive from another directive

我有一个已经有效的指令,并且页面上通常有多个指令,因此它使用隔离范围 'state' 来决定是否显示内容。

<bdb-slideable state="expanded" duration="0.3">
   ...
   element content
   ...
</bdb-slideable>

页面上还有各种其他元素作为指令的触发器,在本例中它可能是一个文档标签,所以我会用一些东西来处理点击和一个跨度来显示正确的或根据状态向下插入符号。

<div class="toggle" ng-click="expanded=!expanded">
    <h4>Documentation</h4>
    <span class="fa" ng-class="{'fa-caret-down':!expanded,'fa-caret-up':expanded}"></span>
</div>

这一切都有效,但它增加了工作量,我必须跟踪我正在使用的状态变量以及在更大的页面上(或者我在模板中拉入的位置,这变得很乱)。此外,需要包装的元素或元素集合并不总是一个,可以是任何文本或标记。

我试图通过属性向将用作切换触发器的元素添加指令,它将管理插入符号的正确显示并注入所有相应的 类。

<h4 bdb-toggle-slideable="documentation">Documentation</h4>

然后给 bdb-slideable 添加一个 name 属性,对应于将被切换的 slidable。

<bdb-slideable name="documentation" state="expanded" duration="0.3">

我的原始指令通过隔离作用域双向绑定公开 'state',

return {
  restrict: 'E',
  scope: { expanded:'=state' },
  ...
     rest of directive
  ... 
};

我想以某种方式在我的新指令中找到具有正确名称的 bdb-slidable 实例,然后获取 'state' 的初始值以正确设置插入符号,然后点击切换插入符号并根据需要设置 bdb-slideable 的 'state' 的值。

所以我有这个切换指令:

app.directive('bdbToggleSlideable', function() {

  function getTemplate(tElement, tAttrs) {
    return  '<div class="toggle" ng-transclude>' +
              '<span ng-class="{\'fa fa-caret-down\':!expanded,\'fa fa-caret-up\':expanded}"></span>' +
            '</div>'
  };

  function link(scope, element, attrs, ctrl, transclude) {

    scope.expanded = scope.target.state;    // ???

    element.bind('click', function() {
      scope.expanded = !scope.expanded;

    });
  }

  return {
      restrict: 'A'
    , scope: { target:'=bdbToggleSlideable'}
    , transclude: true
    , link: link
    , template: function (tElement, tAttrs) {
        return getTemplate(tElement, tAttrs);
    }
  }
});

所以这至少有两点不对。

模板生成的输出没有用 div 包装 H4 然后插入跨度(我希望它生成与我上面显示的手动包装元素相同的格式)它生成了这个。:

<h4 bdb-toggle-slideable="documentation" class="ng-isolate-scope">
  <div class="toggle" ng-transclude="">
    <span class="ng-scope">Test</span>
  </div>
 </h4>

而且我还收到以下错误:

'TypeError: Cannot read property 'state' of undefined'

因为 state.target 未定义,即使我定义了

,也没有在指令的隔离状态下引用目标
scope:  { target:'=bdbToggleSlideable' } 

这必须存在才能编译指令,所以我假设它现在确实知道找到 name="documentation" 的指令,因此未定义为值。

有没有人知道如何实现这一点,或者如何在另一个具有 name="" 属性的指令上获取/设置 'state' 值?

所以我重写了新指令,使其像这样工作:

app.directive('bdbToggleSlideable', function() {

  function getTemplate(tElement, tAttrs) {
    var state = tAttrs.state;
    return  '<div class="toggle" ng-click="'+state+'=!'+state+'">' +
              '<ng-transclude></ng-transclude>' +
              '<span ng-class="{\'fa fa-caret-down\':!'+state+',\'fa fa-caret-up\':'+state+'}"></span>' +
            '</div>'
  };

  return {
      restrict: 'E'
    , transclude: true
    , replace: true
    , template: function (tElement, tAttrs) {
        return getTemplate(tElement, tAttrs);
    }
  }
});

然后我使用以下标记编译到我的页面中

<bdb-toggle-slideable state="expanded">
  <h4>Documentation</h4>
</bdb-toggle-slideable>
<bdb-slideable state="expanded" ng-init="expanded=true" duration="0.3">
  ...
  element content
  ...
</bdb-slideable>

在这生成的标记中,切换元素周围有一个额外的节点和一个额外的属性,但它接近我想要生成的内容。

<div class="toggle" ng-click="expanded=!expanded" state="expanded">
  <ng-transclude>
    <h4 class="ng-scope">Documentation</h4>
  </ng-transclude>
  <span ng-class="{'fa fa-caret-down':!expanded,'fa fa-caret-up':expanded}" class="fa fa-caret-up"></span>
</div>

我仍然必须确保 state="" 属性在切换和可滑动元素上是相同的,并且它们在范围内是唯一的,但由于其管理代码和内部代码略少无需手动干预即可切换状态和插入符排列,比我的好。

当然,这并不是我想要实现的目标,但它确实有效。