我想创建一个指令,该指令根据来自服务的值来检查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>
<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; } } }); } }; });
在指令中添加优先级非常重要,否则,不会评估附加到该元素的其他指令!
您的问题的第一部分“为什么?”是我可以回答的问题:
您遇到的问题是,不能在不调用元素的情况下将指令动态地应用于$compile元素。
$compile
如果$compile(element)(element.scope())在设置属性后调用,则会由于您正在编译自己而导致堆栈溢出,这会导致您进行编译,进而导致您进行编译等。
$compile(element)(element.scope())
第二部分“如何实现”,我遇到了麻烦。我尝试了几种方法(例如用嵌套的内容替换内容ng-if),但是我无法确切地找到您要查找的行为。
ng-if
我认为下一步可能是研究ng- if的代码,并尝试直接在您的指令中实现类似的功能。
这是使它工作的第一步。我希望它需要一些清理和修改才能使其按您真正想要的方式工作。