简体   繁体   English

添加自定义类装饰器时,Angular Injected失败

[英]Angular Injected fail when add custom class decorator

According to this tutorial I try to implement custom decorator the allow us restrict access to the component class base on user role. 根据本教程,我尝试实现自定义装饰器,以允许我们基于用户角色限制对组件类的访问。 otherwise redirect to other component (I know it has other strategies to archive this but it not suit our use case). 否则,重定向到其他组件(我知道它还有其他策略可以对此进行存档,但不适合我们的用例)。

It works as I aspect , but only when I run in local machine not on deploy server . 它按我的方式工作, 但仅当我在本地计算机上运行而不在部署服务器上时才起作用。 Error is like it cannot injected any service or class in constructor of every component the use this decorator ??? 错误就像它无法使用此装饰器在每个组件的构造函数中注入任何服务或类一样?

role-required.decorator.ts 角色required.decorator.ts

export function RoleRequired(roles: string[], redirectUrl = '/forbidden') {

    return function<T extends {new(...args:any[]):{}}> (constructor:T) {

        // save a reference to the original constructor
        const original = constructor;

        // a utility function to generate instances of a class
        function construct(constructor, args) {
            const c : any = function () {
                return constructor.apply(this, args);
            };
            c.prototype = constructor.prototype;
            return new c();
        }

        // the new constructor behaviour
        const f : any = function(router: Router, ...args) {
            console.log("Class: " + original.name);
            this.__verifyRole = JSON.parse(localStorage.getItem("roles")) || [];

            const that = this;
            const isGrant = roles.every((item, index) => {
                return that.__verifyRole.indexOf(item) != -1
            });

            if (!isGrant) {
                router.navigate([redirectUrl]);
            }

            return construct(original, args);
        };

        // copy prototype so intanceof operator still works
        f.prototype = original.prototype;

        // copy metadata to new constructor
        let metadatakeys = Reflect.getMetadataKeys(constructor);
        metadatakeys.forEach(function (key) {
            Reflect.defineMetadata(key, Reflect.getOwnMetadata(key, constructor), f)
        });

        // read dependencies list from 'cls', add our own dependency, and write list to 'newCls'
        let dependencies = Reflect.getOwnMetadata('design:paramtypes', constructor);
        dependencies = [Router].concat(dependencies);
        Reflect.defineMetadata('design:paramtypes', dependencies, f);

        // return new constructor (will override original)
        return f;
    }
}

PREREQUISITE PREREQUISITE

import this class at app.module.ts import 'reflect-metadata'; app.module.ts导入此类app.module.ts -metadata';

USAGE 用法

@RoleRequired(['role.user.chat'])
export class ChatRoomComponent {}

error message is all property of injected class when start component. 错误消息是启动组件时注入类的所有属性。

ERROR TypeError: Cannot read property 'informSoundSettingChange' of undefined 错误TypeError:无法读取未定义的属性'informSoundSettingChange'

package.json 的package.json

{
  "name": "alpha-love-chat-ng",
  "version": "1.0.0",
  "license": "MIT",
  "angular-cli": {},
  "scripts": {
    "ng": "ng",
    "start": "ng serve --deploy / --proxy-config proxy.conf.json",
    "build": "ng build --prod --aot output-hashing none --deploy /",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^4.2.6",
    "@angular/cdk": "^2.0.0-beta.8",
    "@angular/common": "^4.2.6",
    "@angular/compiler": "^4.2.6",
    "@angular/core": "^4.2.6",
    "@angular/forms": "^4.2.6",
    "@angular/http": "^4.2.6",
    "@angular/material": "^2.0.0-beta.8",
    "@angular/platform-browser": "^4.2.6",
    "@angular/platform-browser-dynamic": "^4.2.6",
    "@angular/router": "^4.2.6",
    "angular-datatables": "^4.1.1",
    "angular2-notifications": "^0.7.4",
    "angular2-uuid": "^1.1.1",
    "bootstrap": "^3.3.7",
    "core-js": "^2.4.1",
    "datatables.net": "^1.10.15",
    "datatables.net-dt": "^1.10.15",
    "howler": "^2.0.4",
    "jquery": "^3.2.1",
    "lz-string": "^1.4.4",
    "malihu-custom-scrollbar-plugin": "^3.1.5",
    "moment": "^2.18.1",
    "moment-timezone": "^0.5.13",
    "ng2-modal": "0.0.25",
    "ngx-facebook": "^2.4.0",
    "ngx-infinite-scroll": "^0.5.1",
    "reflect-metadata": "^0.1.10",
    "rxjs": "^5.4.2",
    "rxjs-extra": "^0.1.1",
    "signalr": "^2.2.2",
    "underscore": "^1.8.3",
    "zone.js": "^0.8.4"
  },
  "devDependencies": {
    "@angular/cli": "^1.2.0",
    "@angular/compiler-cli": "^4.2.6",
    "@angular/language-service": "^4.2.6",
    "@types/bootstrap": "^3.3.34",
    "@types/datatables.net": "^1.10.4",
    "@types/howler": "^2.0.2",
    "@types/jasmine": "2.5.45",
    "@types/jquery": "^3.2.6",
    "@types/lz-string": "^1.3.32",
    "@types/moment": "^2.13.0",
    "@types/moment-timezone": "^0.2.34",
    "@types/node": "^6.0.80",
    "codelyzer": "~3.0.1",
    "jasmine-core": "~2.6.2",
    "jasmine-spec-reporter": "~4.1.0",
    "karma": "~1.7.0",
    "karma-chrome-launcher": "~2.1.1",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.2",
    "ts-node": "~3.0.4",
    "tslint": "~5.3.2",
    "typescript": "~2.3.3"
  }
}

According to @n00dl3 suggest in comment.. 根据@ n00dl3建议在评论中。

Seriously I fear this is an AOT limitation... I guess it creates the injection logic at build time so you can't use your decorator with AOT enabled.. 严重的是,我担心这是AOT的限制...我想它会在构建时创建注入逻辑,因此您不能在启用AOT的情况下使用装饰器。

However, I try and it's not work at first because.. 但是,我尝试了,但一开始它不起作用,因为..

"ng build --prod --aot output-hashing none --deploy /" “ ng build --prod --aot输出哈希无--deploy /”

I just remove --aot , but I still have this flag --prod left and by default it will enable --aot true so I fix by --aot false github.com/angular/angular-cli/wiki/build 我只是删除了--aot ,但是我仍然保留了该标志--prod ,默认情况下它将启用--aot true所以我通过--aot false github.com/angular/angular-cli/wiki/build进行修复

Final version 最终版本

"ng build --prod --aot false output-hashing none --deploy /" “ ng build --prod --aot错误的输出-不散列--deploy /”

instead of 代替

"ng build --prod output-hashing none --deploy /" “ ng build --prod输出哈希无--deploy /”

In conclusion remove --aot flag is solved my problem prevent it remove my custom decorator. 最后,删除--aot标志已解决我的问题,防止它删除我的自定义装饰器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM