我想创建一个AngularJs指令,根据一些声明进行授权。
基本上我想在任何html元素(按钮,div,a等)中有一个属性,我在其中指定哪些组可以查看该项目,并且根据当前用户是否具有这些组,该元素将具有{{1设置为true或false。
这是我在打字稿中的指示。我正在注入一项服务,负责检查当前用户是否有任何索赔:
ng-show
我正在使用这个指令,假设例如在myCtrl中我有一个像:
这样的属性//
// Directive to hide or show html element based on group claims for the current user
//
// Usage: <button authorize="mycontroller.authorizedGroupsArray" />
//
namespace app.blocks.directives {
"use strict";
class AuthorizeDirective implements ng.IDirective {
public restrict: string = "A";
public replace: boolean = true;
public scope: any = {
authorizedGroups: "=authorize"
};
constructor(private $compile: ng.ICompileService, private authService: services.IAuthService) {
console.log("authorize directive init");
}
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 el = angular.element(instanceElement);
let groups: Array<string> = (<any>scope).authorizedGroups || [];
let authorized: boolean = this.authService.isUserAuthorized(groups); // returns true if the user has any of the groups among its claims
el.attr("ng-show", String(authorized));
//remove the attribute, otherwise it creates an infinite loop.
el.removeAttr("authorize");
this.$compile(el)(scope);
}
}
angular
.module("app.blocks.directives")
.directive("authorize", AuthorizeDirective.factory());
}
所以在我看来:
public get groupsAuthorized(): Array<string> {
return [
"accounting"
"administrators"
];
}
此代码的问题是有效,但会引发错误
<button type="button" class="btn btn-default" authorize="myCtrl.groupsAuthorized">TEST</button>
指令代码只执行一次,我在执行后删除属性app.globalexceptionhandler.config.ts:28 Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!(…)(anonymous function) @ app.globalexceptionhandler.config.ts:28$apply @ angular.js:17792done @ angular.js:11831completeRequest @ angular.js:12033requestLoaded @ angular.js:11966
angular.js:68 Uncaught Error: [$sce:itype] Attempted to trust a non-string value in a content requiring a string: Context: html
以确保指令不在循环中执行。所以我不太确定会发生什么。
如果我删除隔离范围(注释掉以下内容):
authorize
我尝试在我的指令中获取 //public scope: any = {
// authorizedGroups: "=authorize"
//};
属性中传递的参数:
authorize
那么这个let groups: any = instanceAttributes.authorize;
变量的值不是数组本身,而是字符串文字groups
,它是无效的,因为我想要一个组数组,而不是数组的名称。
为什么隔离范围导致摘要错误?如何解决问题并获取指令中的组数组?
更新替代方法:
我有一个解决方法,基本上我将指令传递给字符串而不是数组。 我会让控制器返回一个字符串,其中包含以逗号分隔的组:
"myCtrl.groupsAuthorized"
然后我会以类似的方式使用该指令,这次只传递&#34; magic&#34;字符串首先在视图中呈现。
public get groupsAuthorized(): string {
let groups: Array<string> = [
"accounting",
"administrators"
];
return groups.join(",");
}
最后在我的指令中,我将这个逗号分隔的字符串转换为这样的数组:
<button type="button" class="btn btn-default" authorize="{{myCtrl.groupsAuthorized}}">TEST</button>
但这不是一个优雅的解决方案,如果逗号分隔的组的格式不正确或者每个逗号后面都有空格,它可能会导致问题!我仍然想让我的指令参数直接传递一个数组。