从另一个指令触发指令

时间:2015-03-23 01:14:48

标签: angularjs angularjs-directive angularjs-scope

我有一个已经有效的指令,并且页面上经常有多个指令,因此它使用隔离范围“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>

这一切都有效,但它的添加工作,我必须跟踪我正在使用的状态变量和更大的页面(或我拉入模板的地方变得混乱)。此外,需要包装的元素或元素集合并不总是a,可以是任何文本或标记。

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

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

然后将一个name属性添加到与将要切换的可滑动对应的bdb-slideable。

<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然后插入span(我希望它生成与上面显示的手动包装元素相同的格式)它生成了这个:

<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'值?

1 个答案:

答案 0 :(得分:0)

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

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>

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

<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 =“”属性相同,并且它们在范围内是唯一的,但是因为它的管理代码和内部切换状态略少和插入符号没有人工干预,比我的更好。

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