对于以下情况,我一直在努力使用我的方法。我有一个自定义指令authorize
,我在其中传递了一个组的名称。如果当前用户在他的个人资料中有这个组,那么该元素将是可见的,否则该元素将被隐藏。例子:
<button class="btn btn-default" role="button"
ng-click="myVm.edit()"
authorize="{{myVm.groupName}}"><!--groupName = "accountants"-->
<span class="fa fa-edit" aria-hidden="true"></span> Edit
</button>
以及我在打字稿中使用链接功能的原始指令authorize.ts
(因为我在 DOM 上操作)
namespace app.blocks.directives {
"use strict";
class AuthorizeDirective implements ng.IDirective {
public restrict: string = "A";
public replace: boolean = true;
constructor(private $compile: ng.ICompileService, private authService: services.IAuthService) {
}
public static factory(): ng.IDirectiveFactory {
const directive = ($compile: ng.ICompileService, authService: services.IAuthService) =>
new AuthorizeDirective($compile, authService);
directive.$inject = [
"$compile",
"app.services.AuthService"
];
return directive;
}
public link(scope: ng.IScope, instanceElement: ng.IAugmentedJQuery, instanceAttributes: ng.IAttributes): void {
let groupName: string = (<any>instanceAttributes).authorize;
let element = angular.element(instanceElement);
let hasGroup: boolean = this.authService.hasGroup(groupName);
element.attr("ng-show", String(hasGroup));
//remove the attribute, otherwise it creates an infinite loop.
element.removeAttr("authorize");
this.$compile(element)(scope);
}
}
}
angular
.module("app.blocks.directives")
.directive("authorize", AuthorizeDirective.factory());
}
这工作正常,如果 authService 返回 false 因为用户不属于该组(即:),则隐藏按钮"accountants"
。
当我的 DOM 元素也有ng-show
orng-hide
指令时,就会出现问题。例子:
<button class="btn btn-default" role="button"
ng-hide="myVm.isDeleted"
ng-click="myVm.edit()"
authorize="{{myVm.groupName}}">
<!--groupName = "accountants"-->
<span class="fa fa-edit" aria-hidden="true"></span> Edit
</button>
当myVm.isDeleted = true
它似乎覆盖了我的指令的结果并显示了 DOM 元素时(当它不应该因为用户不属于我的authorize
指令所指定的组时)。
我意识到指令中有一些优先级(默认情况下0
),当两个指令具有相同的优先级时,它们会根据文档按字母顺序执行。这篇文章对理解这一点很有帮助。
所以我在这里有一些选择:
让我的授权指令评估条件以
ng-hide
进行ng-show
计算(即:如果 ng-hide 说应该显示元素但用户没有特定的组,则应该隐藏元素)。我找不到myVm.isDeleted
在我的指令链接的函数中访问的方法。如果有人知道我会对这种方法感到满意。让我的
authorize
指令在任何其他指令之前执行,并依赖 angular 稍后根据ng-show
or确定可见性ng-hide
(即:如果我的authorize
指令确定元素应该隐藏,因为用户不属于给定的组,那么它应该转换 DOM元素并制作它ng-show="false"
,以便稍后隐藏元素。这种方法似乎不起作用,DOM似乎是正确的,我可以看到按钮有 ng-show="false" 但由于某种原因我仍然看到屏幕上的按钮,所以好像 Angular 不知道它必须隐藏该元素。有趣的是,如果我移动到另一个选项卡,然后我回到同一个选项卡(视图被重新加载并且指令重新-执行)然后它工作正常。这是怎么回事?.
我选择了选项 2,这是似乎可以正常操作 DOM 的代码,但是 Angular 之后没有应用 ng-show 指令,因此结果与预期不符。
public priority: number = 999; //High priority so it is executed BEFORE ng-show directive
public link(scope: ng.IScope, instanceElement: ng.IAugmentedJQuery, instanceAttributes: ng.IAttributes): void {
let groupName: string = (<any>instanceAttributes).authorize;
let element = angular.element(instanceElement);
let ngShow: string = (<any>instanceAttributes).ngShow;
let ngHide: string = (<any>instanceAttributes).ngHide;
let hasGroup: boolean = this.authService.hasGroup(groupName);
let ngHideValue = ngHide ? "!" + ngHide : "";
let ngShowValue = ngShow ? ngShow : "";
//if hasGroup, use whatever ng-show or ng-hide value the element had (ng-show = !ng-hide).
//if !hasGroup, it does not matter what value the element had, it will be hidden.
if (hasGroup) {
element.attr("ng-show", (ngShowValue + ngHideValue) || "true");
} else {
element.attr("ng-show", "false");
}
element.removeAttr("ng-hide");
//remove the attribute, otherwise it creates an infinite loop.
element.removeAttr("authorize");
this.$compile(element)(scope);
}