角度2。如何在检查访问后隐藏(不呈现)菜单中的 link?

Angular2. How to hide(no-render) the link in the menu after check access?

检查ACL访问后,需要根据"routerLink"在菜单中隐藏link。我不想在应用程序中的每个元素 link 上使用 angular 指令 "*ngIf"(需要在 routerConfig 定义中全局执行)

内容可以在组件上使用注解@CanActivate控制,但需要在菜单中隐藏link

我尝试使用覆盖 "routerLink" 指令来做到这一点,但是在这个指令中覆盖后无法访问我定义的扩展参数(资源和特权)路由器配置

示例:

@Component({})
@RouteConfig([{   
    path: '/dashboard', 
    name: 'Dashboard', 
    component: DashboardComponent, 
    data: {'resource':'account', 'privilage':'show'} 
}])

但无法访问 "routerLink" 中的此配置数据 (routerData)。

知道怎么做吗?

第二个版本

多级菜单和从 routerConfig 定义访问(扩展数据配置)仍然有问题。

主要成分

@RouteConfig([
    { path:'/dashboard',   name: 'DashboardLink',   component: DashboardComponent,  data: { res: 'dasboard', priv: 'show'}, useAsDefault: true },
    { path:'/user/...',    name: 'UserLink',        component: UserComponent,       data: { res: 'user', priv: 'show'} },
 ])

@Component({
    selector: 'main-app',
    template: `
            <ul class="left-menu">
                <li><a secured [routerLink]="['UserLink']">User</a>
                    <ul>
                        <li><a secured [routerLink]="['ProfileLink']">Profile</a></li>
                    </ul>
                </li>
                <li><a secured [routerLink]="['HomeLink']">Home</a></li>
                <li><a secured [routerLink]="['DashboardLink']">Dashboard</a></li>
            </ul>

            <router-outlet></router-outlet>
    `
})
export class MainComponent {

}

用户组件

@RouteConfig([
    { path: '/profile', name: 'ProfileLink', component: ProfileComponent, data: {res: 'user', priv: 'details'} },
])
@Component({ ... })
export class UserComponent {
}

配置文件组件

@Component({ ... })
export class ProfileComponent {

}

我的安全指令

@Directive({
    selector: '[secured]'
})
export class SecuredDirective {

    @Input('routerLink')
    routeParams: any[];

    /**
     * 
     */
    constructor(private _viewContainer: ViewContainerRef, private _elementRef: ElementRef, private router:Router) {
    }

    ngAfterViewInit(){
        //Get access to the directives element router instructions (with parent instructions)
        let instruction = this.router.generate(this.routeParams);
            //Find last child element od instruction - I thing thats my component but I am not sure (work good with two levels of menu)
            this.getRouterChild(instruction);
    }

    private getRouterChild(obj: any){
        var obj1 = obj;
        while(true) {
            if( typeof obj1.child !== 'undefined' && obj1.child !== null ){
                obj1 = obj1.child;
            } else {
                break;
            }  
        }
        this.checkResPrivAcl(obj1.component.routeData.data)
    }
    private checkResPrivAcl(aclResAndPriv: any){

        let hasAccess = CommonAclService.getInstance().hasAccess(aclResAndPriv['res'], aclResAndPriv['priv']);

        if (!hasAccess) {
            let el : HTMLElement = this._elementRef.nativeElement;
            el.parentNode.removeChild(el);   
        }

        console.log("CHECK ACL: " + aclResAndPriv['res'] + " | " + aclResAndPriv['priv']);
    }
}

此解决方案仅适用于菜单的子项,不适用于主级菜单,并且不确定该解决方案是否适用于多级菜单。

我尝试不同的方法来解决这个问题我尝试访问指令中的 RouterConfig 定义(和我的 routerData 扩展配置)并使用 通过 link 的别名检查元素@Input('routerLink') 但找不到如何访问 RouterConfig。

当路由在 angular2 中激活时,它默认添加 .router-link-active class 到 link.

所以我会hidedisable激活路由,

@Component({
  selector: 'my-app',

  // to hide it,

  styles: [".router-link-active { Display: none;}"], //just add it in single line...

  // to hide it,

  styles: [".router-link-active { pointer-events: none;cursor: default;opacity: 0.6; }"], //just add it in single line...

  template:'...'
)}

我认为您可以创建一个专门的指令来执行此操作。该指令将附加到包含 routerLink 的同一 HTML 元素上。这样您就可以访问本机元素和 RouterLink 指令:

@Directive({
  selector: '[secured]'
})
export class Secured {
  constructor(private routerLink:RouterLink,private eltRef:ElementRef) {
    (...)
  }
}

并这样使用它:

@Component({
  selector: 'app',
  template: `
    <router-outlet></router-outlet>
    <a secured [routerLink]="['./Home']">Home</a>
  `,
  providers: [ ROUTER_PROVIDERS ],
  directives: [ ROUTER_DIRECTIVES, Secured ],
  pipes: []
})
@RouteConfig([
  {
    path: '/home',
    name: 'Home',
    component: HomeComponent,
    useAsDefault: true,
    data: {'resources':'account', 'privilages':'show'} 
  },
  (...)
])
export class ...

基于RouterLink指令实例,您可以访问定义路由时指定的数据,并在必要时隐藏元素:

export class Secured {
  @HostBinding('hidden')
  hideRouterLink:boolean;

  constructor(private routerLink:RouterLink) {
  }

  ngAfterViewInit()
    var data = this.routerLink._navigationInstruction.component.routeData.data;
    this.hideRouterLink = this.shouldBeHidden(data);
  }

  (...)
}

参见 src/app.ts

中的 this plunkr

编辑

the issue by Brandon 中所建议,我们可以从 routerLink 属性中指定的值重新生成组件指令:

export class Secured {
  @HostBinding('hidden')
  hideRouterLink:boolean;

  @Input('routerLink')
  routeParams:string;

  constructor(private router:Router) {
  }

  ngAfterViewInit() {
    var instruction = this.router.generate(this.routeParams);
    var data = instruction.component.routeData.data;
    this.hideRouterLink = this.shouldBeHidden(data);
  }

  (...)
}