向angularjs指令添加和编译属性

时间:2016-02-11 16:23:51

标签: javascript angularjs angularjs-directive

我有一个指令<my-dir></my-dir>,指令应始终具有通过角度属性提供的特定功能:<my-dir ng-show="ctrl.shown"></my-dir>。这里ctrl是在指令定义上通过controllerAs: 'ctrl'定义的控制器。

我希望通过在编译指令时自动添加属性来简化此指令并避免错误。这样其他用户只需键入<my-dir>即可。向指令添加属性很简单,但这些新属性似乎没有被编译。

app.directive("myDir", function() {
  console.log('myDir');
  return {
    restrict: 'E',
    controller: 'DirectiveController',
    controllerAs: 'ctrl',
    template: '<span>Controller Content</span>'

    // Attempt to attach the 'ng-show' attribute to the element

    link: function($scope, $element, attrs) {
      $element.attr('ng-show', 'ctrl.shown');
    }

  };
});

我尝试了很多不同的事情:在link:中添加属性,在compile:中添加属性,甚至在添加属性后使用$compile($element[0]['my-dir'])($scope)

示例plnkr:http://plnkr.co/edit/PREavAIn1vqUdZYLsypt?p=preview

示例plnkr使用ctrl.shownhttp://plnkr.co/edit/dTWIzClZG4YpE76AMCWk?p=preview

3 个答案:

答案 0 :(得分:1)

<强>更新

所以将这个逻辑放入指令的编译步骤似乎是正确的方向:

...
compile: function(tElem, tAttrs) {

  // appears that you need to remove this attribute  
  // to stop the directive from looping infinitely 
  // through the compile step
  tElem.removeAttr('my-dir'); 
  tElem.attr('ng-hide', 'true');

  return function(scope) {
    $compile(tElem)(scope);
  }
}

这是更新的plnkr:http://plnkr.co/edit/uyfJl8b1w5esYGv7SIsx?p=preview

请参阅this question

答案 1 :(得分:1)

OP解决方案

基于paul trone's answer to this topic,我想出了一个适合我的解决方案。

基本上我在添加角度属性后重新编译元素。为了避免无限循环,我还使用自定义标记标记元素,并在标记元素时停止编译。

这样我可以多次部署<my-dir></my-dir>,每个都在指令的根级别具有隐式自定义功能。通过这种方式,可以使用ng-show来隐藏整个指令,而不仅仅是内部的模板化元素。

angular.module('app', []);

angular.module('app').directive("myDir", function($compile) {
  return {
    restrict: 'E',                     // I prefer this directive to be Element-only
    controller: 'DirectiveController',
    controllerAs: 'ctrl',
    template: '<span>Controller Content</span>',

    /**
     * Add the necessary angular attributes
     *   along with a 'compiled' attribute as tag
     *   such that the element doesn't infinitely compile itself
     *
     * This still allows multiple of the same directive to be
     *   compiled at the same time
     */
    compile: function(tElem, tAttrs){

      // Check if the element has been tagged
      if(! tAttrs['compiled']) {

        // Tag the element so it doesn't compile again
        tElem.attr('compiled', true)

        // Add custom angular attributes
        tElem.attr('ng-show', 'ctrl.shown');

        // Recompile
        return function(scope) { $compile(tElem)(scope); };
      }
    }
  };
});

angular.module('app').controller("DirectiveController", function() {
    var shown = false;
});

示例:http://plnkr.co/edit/wbs0vcFmz15oL2twm6AC?p=preview

或者可以将一个观察者附加到一个变量,该变量可以切换类似于ng-show如何工作的类,但是会开始复制ng-show属性所需的确切功能。

答案 2 :(得分:-1)

不确定我是否理解您要正确执行的操作,但为什么不直接将属性添加到模板中?

template: '<span ng-show="ctrl.shown">Controller Content</span>'