在指令

时间:2016-08-24 23:52:22

标签: angularjs typescript angularjs-scope directive angular-digest

我想创建一个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>

但这不是一个优雅的解决方案,如果逗号分隔的组的格式不正确或者每个逗号后面都有空格,它可能会导致问题!我仍然想让我的指令参数直接传递一个数组。

0 个答案:

没有答案