一尘不染

AngularJS:以编程方式将ngIf添加到指令的最佳实践是什么?

angularjs

我想创建一个指令,该指令根据来自服务的值来检查dom中是否应包含元素(例如,检查用户角色)。

相应的指令如下所示:

angular.module('app', []).directive('addCondition', function($rootScope) {
    return {
        restrict: 'A',
        compile: function (element, attr) {
          var ngIf = attr.ngIf,
              value = $rootScope.$eval(attr.addCondition);

          /**
           * Make sure to combine with existing ngIf!
           * I want to modify the expression to be evalued by ngIf here based on a role 
           * check for example
           */
          if (ngIf) {
            value += ' && ' + ngIf;
          }

          attr.$set('ng-if', value);
        }
    };
});

最后,该元素具有ng-if属性,但由于某种原因它不适用于该元素,并且仍然存在于dom中。因此,这显然是错误的方法。

这个小提琴显示了问题:http :
//jsfiddle.net/L37tZ/2/

谁能解释为什么会这样?还有其他方法可以实现类似的行为吗?应该考虑现有的ngIf。

解:

用法: <div rln-require-roles="['ADMIN', 'USER']">I'm hidden when theses role requirements are not satifisfied!</div>

.directive('rlnRequireRoles', function ($animate, Session) {

  return {
    transclude: 'element',
    priority: 600,
    terminal: true,
    restrict: 'A',
    link: function ($scope, $element, $attr, ctrl, $transclude) {
      var block, childScope, roles;

      $attr.$observe('rlnRequireRoles', function (value) {
        roles = $scope.$eval(value);
        if (Session.hasRoles(roles)) {
          if (!childScope) {
            childScope = $scope.$new();
            $transclude(childScope, function (clone) {
              block = {
                startNode: clone[0],
                endNode: clone[clone.length++] = document.createComment(' end rlnRequireRoles: ' + $attr.rlnRequireRoles + ' ')
              };
              $animate.enter(clone, $element.parent(), $element);
            });
          }
        } else {

          if (childScope) {
            childScope.$destroy();
            childScope = null;
          }

          if (block) {
            $animate.leave(getBlockElements(block));
            block = null;
          }
        }
      });
    }
  };
});

在指令中添加优先级非常重要,否则,不会评估附加到该元素的其他指令!


阅读 164

收藏
2020-07-04

共1个答案

一尘不染

您的问题的第一部分“为什么?”是我可以回答的问题:

您遇到的问题是,不能在不调用元素的情况下将指令动态地应用于$compile元素。

如果$compile(element)(element.scope())在设置属性后调用,则会由于您正在编译自己而导致堆栈溢出,这会导致您进行编译,进而导致您进行编译等。

第二部分“如何实现”,我遇到了麻烦。我尝试了几种方法(例如用嵌套的内容替换内容ng-if),但是我无法确切地找到您要查找的行为。

我认为下一步可能是研究ng-
if
的代码,并尝试直接在您的指令中实现类似的功能。

这是使它工作第一步。我希望它需要一些清理和修改才能使其按您真正想要的方式工作。

2020-07-04