Angular2:如何为多个组件提供相同的保护

时间:2017-01-26 13:14:58

标签: angular angular2-routing

在Angular2中,是否可以使用相同的防护(例如CanActivate或CanDeactivate),它可以应用于多个组件?

这是MyComponent1的守卫:

@Injectable()
export class MyGuard implements CanDeactivate<MyComponent1> {

  canDeactivate(component: MyComponent1): Promise<boolean> {
    // my code here
  }
}

我想要MyComponent2MyComponent3等完全相同的保护。

我该如何实现?我需要按组件声明一个新的防护类,还是可以重用我的班级MyGuard

4 个答案:

答案 0 :(得分:4)

只需将相同的防护添加到您希望应用它的每条路线。

或者,您也可以创建无组件父路线,在其中添加防护,并且所有子路线将受同一防护保护。 这仅在组件全部处于同级路由时才有效。

Angular DI不支持泛型类型参数。作为一种解决方法,这应该做你想要的(事件虽然可能比你想要的更冗长):

routes: [
  { path: 'x', component: MyComponent1, canDeactivate: [new Inject('CanDeactivateMyComponent1') },
  { path: 'y', component: MyComponent2, canDeactivate: [new Inject('CanDeactivateMyComponent2') },

]


@NgModule({
  providers: [
    {provide: 'CanDeactivateMyComponent1', useFactory: () => new CanDeactivate<MyComponent1>()},
    {provide: 'CanDeactivateMyComponent2', useFactory: () => new CanDeactivate<MyComponent2>()},

  ],
})
export class AppModule {}
  ...
})

答案 1 :(得分:2)

路线:

routes: [
    { path: 'x', component: MyComponent1, canDeactivate: ['MyGuard '] },
    { path: 'y', component: MyComponent2, canDeactivate: ['MyGuard '] },
]

守卫:

@Injectable()    
export class MyGuard implements CanDeactivate<MyComp1 | MyComp2> {    
    constructor() { }    

  canDeactivate(    
    component: PermissionSetsComponent | NodeAccessGroupComponent,    
    ): Observable<boolean> | Promise<boolean> | boolean {    

 // Your code here    
 }    
}

答案 2 :(得分:1)

基于Günter Zöchbauer's answer,我有一个解决方案。

后卫:

@Injectable()
export class MyGuard<T> implements CanDeactivate<T> {
  // Maybe some DI here, just inject them into useFactory and deps
  constructor() {}

  canDeactivate(component: T): Promise<boolean> {
    // my code here
  }
}

只是提供你的警卫:

routes: [
  { path: 'x', component: MyComponent1, canDeactivate: ['CanDeactivateMyComponent1'] },
  { path: 'y', component: MyComponent2, canDeactivate: ['CanDeactivateMyComponent2'] },

]


@NgModule({
  providers: [
    {provide: 'CanDeactivateMyComponent1', useFactory: () => new MyGuard<MyComponent1>()},
    {provide: 'CanDeactivateMyComponent2', useFactory: () => new MyGuard<MyComponent2>()},

  ],
})
export class AppModule {}
  ...
})

答案 3 :(得分:0)

它只是冗长而另一种选择是使用继承来创建一个新的专业守卫。

我的通用后卫看起来像这样:

// this goes on the component itself
export interface IUnsavedChangesComponent
{
    hasUnsavedChanges(): boolean;
} 

@Injectable()
export class SaveFormsGuard<C extends IUnsavedChangesComponent> implements CanDeactivate<C>
{
    constructor()
    {
        console.log("SAVEFORMSGUARD");
    }

    canDeactivate(component: C)
    {
        var hasUnsavedChanges = component.hasUnsavedChanges();

        ... dialog box logic ...

        return !hasUnsavedChanges;
    }
}

所以我创造了新的警卫

export class SaveFormsGuard_OrderEditor extends SaveFormsGuard<OrderEditorComponent> { }
export class SaveFormsGuard_CustomerEditor extends SaveFormsGuard<CustomerEditorComponent> { }

你仍然必须将它们都放在提供者列表中,所以它并没有像我希望的那样简单 - 但如果你还需要扩展逻辑,可能是一个很好的模式以其他方式守护你。