参数化函数返回Angular中的ModuleWithProviders

时间:2018-02-12 12:45:31

标签: angular typescript angular5

我有一个由几个组件组成的应用程序,每个组件都定义了自己的路由状态子集。根据集成这些组件的应用程序,它们( app )提供父状态,在该状态下应放置一些组件状态。即。

组件状态:

[{
  name: 'component',
  url: '/component',
  component: ComponentRootComponent,
  abstract: true,
  default: '.list'
}, {
  name: 'component.list',
  url: '',
  component: ComponentListComponent
},...]

这是一些应用程序部分模块:

@NgModule({
  declarations: ...,
  imports: [
    UIRouterModule.forChild({ states: SECTION_STATES }),

    SomeComponentModule,
    UIRouterModule.forChild({
      states: RouterUtil.setParentState(SECTION_STATES[0].name, SOME_COMPONENT_STATES)
    })
  ]
})
export class AppSectionModule {}

setParentState()函数只是迭代组件状态,并在前面加上父状态名称,因此它们会低于特定的路由状态。

这一切都很棒,但我没有为每个组件添加两个导入,我认为如果我提供了一个带有我的模块的函数会更好,这样我就可以为每个组件提供单个但可配置的导入。

@NgModule({
  declarations: ...,
  imports: [
    UIRouterModule.forChild({ states: SECTION_STATES }),
    SomeComponentModule.importFor(SECTION_STATES[0].name)        
  ]
})
export class AppSectionModule {}
因此,

importFor应该返回ModuleWithProviders类型,它是我的原始组件模块的包装器,它还定义组件路由并将其放在特定的父路由下:

export class SomeComponentModule {
  public static importFor(parentState: string): ModuleWithProviders {
    return {
      ngModule: SomeComponentModule,
      providers: [
        // what do I do here?
      ]
    };
  }
}

我如何实现这样的功能?我不知道如何在此功能中呼叫或UIRuterModule.forChild(...)?这是我试图解决的主要问题。

2 个答案:

答案 0 :(得分:0)

使用"隐藏"模块,你可以做到这一点。

第一个模块有一个forRoot()或在你的情况下有一个importFor() 其中有一个指向隐藏模块的ngModule。

此模块是调用importFor时调用导入的模块。 然后它导入原始模块并导出它以使其显示为隐藏。

我发现这是制作可重复使用模块的好方法,我可以简单地将其放入我的项目中,并且所有内容都配置了reducers,effects,routes和all:)

@NgModule({
  imports: [
    SharedModule,
  ],
  declarations: [
    ...SHARED_COMPONENTS,
  ],
  exports: [
    ...SHARED_COMPONENTS,
  ]
})
export class SecurityModule {

  // when the user imports SecurityModule.forRoot() in the app module what we really import is the RootSecurityModule
  // but it will also create the IsAuthenticated guard
  // it also imports all the feature stuff such as reducers, effects and routes

  // if we then later on need to access shared components from the SecurityModule we can import the module without the forRoot()
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: RootSecurityModule, 
      providers: [
        IsAuthenticatedGuard,
      ],
    };
  }
}

@NgModule({
  imports: [

    // import the above module so that we get all the shared declarations
    SecurityModule,

    // import the "include once" modules for security
    StoreModule.forFeature('security', securityReducer),
    EffectsModule.forFeature([
      SecurityEffects
    ]),
    SecurityRoutingModule,
  ],

  // we need to export the SecurityModule otherwise SecurityModule.forRoot() will not mean the same thing as SecurityModule
  exports: [
    SecurityModule,
  ]
})
export class RootSecurityModule {}

答案 1 :(得分:0)

检查UIRouterModule实际上做了什么,这似乎按预期工作:

export class SomeComponentModule {
  public static importBelowState(parentState: string): ModuleWithProviders {
    return {
      ngModule: SomeComponentModule,
      providers: UIRouterModule.forChild({ states: RouterUtil.setParentState(parentState, SOME_COMPONENT_STATES) }).providers
    };
  }
}

所以现在我可以导入组件模块,同时也可以在问题中配置其路由状态:

@NgModule({
  declarations: ...,
  imports: [
    UIRouterModule.forChild({ states: SECTION_STATES }),
    SomeComponentModule.importBelowState(SECTION_STATES[0].name)        
  ]
})
export class AppSectionModule {}