Angular2. How to hide (non-visualize) a link in a menu after checking access?

You need to hide the link in the menu based on "routerLink" after checking ACL access. I do not want to use the angular "* ngIf" directives for each link to an element in the application (I need to do this globally by the definition of routerConfig)

Content can be controlled using the @CanActivate annotation on components, but you need to hide the link in the menu

I try to do this with an override of the routerLink directive, but in these directives, after overwriting, it is impossible to access my advanced parameter defined (resources and privileges) in routerConfig

Example:

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

But it is not possible to access the configuration data (routerData) in "routerLink".

Some ideas how to do this?

Second version

The layered menu and stiil have problems accessing (expanding the data configuration) from the routerConfig definition.

Main component

 @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 { } 

Custom component

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

Component Profile

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

My safe directives

 @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']); } } 

This solution only works for a child menu item that does not work with the main menu level, and is not sure if this works correctly in a multi-level menu.

I am trying to solve this problem. I am trying to access the definition of RouterConfig (and my extension routerData) in directives and check the element by the name of the link alias using @Input ('routerLink') , but cannot find how I can access the RouterConfig.

+4
angular angular2-routing angular2-directives
source share
3 answers

I think you could create a special directive for this. This directive will attach to the same HTML element that contains routerLink one. Thus, you will have access to both the source element and the routerLink directive:

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

and use it as follows:

 @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 ... 

Based on the instance of the routerLink directive routerLink you can access the data that you specified when defining the route and, if necessary, hide the element:

 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); } (...) } 

See this plunkr in src/app.ts : https://plnkr.co/edit/SBoFVo?p=preview

Edit

As suggested in the https://github.com/angular/angular/issues/7641 release from Brandon ( https://github.com/brandonroberts ), we could restore the component command from the value specified in the routerLink attribute:

 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); } (...) } 
+2
source share

when a route becomes active in angular2, it adds the .router-link-active class .router-link-active by default.

So, I hide or disable activated the route,

 @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:'...' )} 
0
source share

Maybe the best way to remove such an item?

 @Directive({ selector: '[secured]' }) export class Secured { @HostBinding('hidden') hideRouterLink:boolean = true; constructor( private routerLink:RouterLink, private _elementRef: ElementRef) { } ngOnInit() { //how to get access to this private variable? console.log(this.routerLink._navigationInstruction.component.routeData.data); //place for implementation of service:acl if(true) { let el : HTMLElement = this._elementRef.nativeElement; el.parentNode.removeChild(el); } } } 

(Thierry Templier) But still cannot access my exbound data (routerData)

0
source share

All Articles