2016-03-16 25 views
4

在檢查ACL訪問之後,需要基於「routerLink」隱藏菜單中的鏈接。我不想用角指令「* ngIf」在應用程序的每個元素鏈接(需要做的globaly在routerConfig定義)Angular2。如何在檢查訪問後隱藏(無呈現)菜單中的鏈接?

內容可以在組件使用註釋@CanActivate CONTROLL但需要隱藏菜單鏈接

我試圖做到這一點與覆蓋「routerLink」指令,但在這個指令後覆蓋不能routerConfig

讓我的擴展PARAM定義(資源的privilages)訪問

例子:

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

,但不能得到在 「routerLink」 上網本配置數據(routerData)。

有些想法該怎麼做?

第二個版本

多級菜單和stiil有來自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擴展配置)的指令,並通過使用@input(「routerLink」),但鏈接的別名檢查元素不知道如何才能訪問RouterConfig。

+0

我不明白什麼是'檢查access'? – micronyks

+0

我的意思是「檢查訪問」訪問者是否有權訪問鏈接 - 數據中定義的資源:{'resource':'account','privilage':'show'} –

回答

2

我認爲,你可以創建一個專用的指令來做到這一點。該指令將附加在包含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); 
    } 

    (...) 
} 

請參閱本plunkr在src/app.ts文件:https://plnkr.co/edit/SBoFVo?p=preview

編輯

正如布蘭登(https://github.com/brandonroberts)在發行https://github.com/angular/angular/issues/7641建議,我們可以重新從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); 
    } 

    (...) 
} 
+0

我喜歡這個,看看我真的接近你的解決方案,請告訴我如何讓這個元素無渲染器(我不想只隱藏在CSS風格 - 我的錯誤與後問題我的意思是隱藏= no-renderer) –

+0

是的,你絕對是對的!使用'@ HostBinding'這是一個更好的解決方案;-)我更新了我的答案和相應的plunk ... –

+0

仍然有一些問題,bcs找到2個錯誤: - [第一]沒有隱藏的鏈接 - [second]錯誤TS2341:屬性'_navigationInstruction'是私有的,只能在類'RouterLink'中訪問(不知道爲什麼這個工作在plunker中) –

0

當路徑在angular2中變爲活動狀態時,它默認將.router-link-active類添加到鏈接。

所以我會hidedisable本actived路線,

@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

這就是你需要的嗎? – micronyks

+0

感謝您的回答,但是,如果visitior沒有ACL訪問權限(鏈接),我想隱藏刪除鏈接。 不隱藏活動鏈接像你說的。 –

0

可以是更好的辦法去除那樣的元素?

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

(蒂埃裏TEMPLIER),但仍無法獲得訪問我的exend數據(routerData)