考虑以下指令:
class HasPermissionDirective {
constructor(PermissionService) {
this.restrict = 'A';
this.priority = 1005;
this.PermissionService = PermissionService;
}
compile(element, attrs) {
let permission = _.trim(attrs.hasPermission),
hide = _.get(attrs, 'hideOnly'),
$element = angular.element(element);
if (permission && !this.PermissionService.hasPermission(permission)) {
if (!_.isUndefined(hide)) {
hide = _.trim(hide);
if (hide === 'visibility') {
$element.css('visibility', 'hidden');
} else {
$element.hide();
}
} else {
$element.remove();
}
}
}
link($scope, $element, attrs, ctrl) {
$scope.$destroy();
}
}
HasPermissionDirective.$inject = ['PermissionService'];
现在的问题是,$ scope。$ destroy()总是被执行,对于指令附加到的每个元素范围(当然)。
当我现在添加" isRemoved"成员变量,如果删除了元素,则将其设置为true,并在链接函数中执行以下操作:
if (this.isRemoved) {
$scope.$destroy();
}
当然,只要删除了至少一个元素,就会为每个元素范围触发$ scope。$ destroy(),因为该指令作为单例处理,而不是作为实例处理。
我无法向元素节点添加任何信息,因为它似乎在编译后被删除,并且只是一个注释节点" ngInclude:undefined" (不,我没有删除节点,我添加了一个数据属性,并希望将其置于链接函数中:$element.data('remove', true)
然后想要$ destroy和remove())。编辑:这似乎是ngInclude指令的转换行为。
如果我从link-function中删除$ scope。$ destroy()并删除该节点,则ngInclude-directive仍在运行...
我想要什么?我只是想在编译时从DOM中删除元素,因为当前用户没有查看此元素/指令/视图的权限,我也想避免进一步处理指令(在我的情况下,ng-include不应该是不必要的)请求模板(因为我们的服务器无论如何都会响应401)等等。
更新:我想我需要一种在编译函数内部设置terminal
选项的方法来停止处理即将发生的指令。我的问题是ngInclude正在运行,即使之前删除了该元素。
答案 0 :(得分:1)
找到解决方案!我还必须使用transclusion(在我检查ngIf的impl之后很明显)并且它唯一可能在(pre / post)链接函数内部,所以这里是impl。遇到类似问题的人:
class HasPermissionDirective {
constructor(PermissionService) {
this.restrict = 'A';
this.priority = 1011; // high prio so the element is removed before all other directives can be processed
this.transclude = 'element';
this.$$tlb = true; // BAD! But w/o, transclusion for different directives won't work :(
this.PermissionService = PermissionService;
}
preLink($scope, $element, attrs, ctrl, $transclude) {
let $newScope = $scope.$new(),
hide = _.get(attrs, 'hideOnly');
$transclude($newScope, ($clone) => {
if (!this.PermissionService.hasPermission(_.trim(attrs.hasPermission))) {
if (!_.isUndefined(hide)) {
hide = _.trim(hide);
if (hide === 'visibility') {
$clone.css('visibility', 'hidden');
} else {
$clone.hide();
}
} else {
$newScope.$destroy();
$newScope = null;
$clone.remove();
$clone = null;
}
} else {
// in case the user has the permission we have to attach the element to the DOM (cause of transclusion)
$element.after($clone);
}
});
}
}
HasPermissionDirective.$inject = ['PermissionService'];
我也把实现外包给控制器,所以我可以重用逻辑,但我不想提供一个完整的例子来澄清:)