NgModule嵌套forRoot

时间:2017-08-03 17:09:29

标签: angular typescript

考虑到有一个模块

@NgModule({
    imports: [
        Ng2Webstorage.forRoot({ prefix: 'SOME_PREFIX' }),
        FooModule.forRoot(...),
        BarModule,
    ],
    exports: [
        Ng2Webstorage,
        FooModule,
        BarModule,
    ]
})
class FeatureModule {
    static forRoot(config): ModuleWithProviders {
        return {
            ngModule: FeatureModule,
            providers: [...]
        };
    }
}

如何动态地将prefix传递给Ng2Webstorage.forRoot?像:

@NgModule({
    imports: [
        BarModule,
    ],
    exports: [
        Ng2Webstorage,
        FooModule,
        BarModule,
    ]
})
class FeatureModule {
    static forRoot(config): ModuleWithProviders {
        return {
            ngModule: FeatureModule,
            imports: [
                Ng2Webstorage.forRoot({ prefix: config.name }),
                FooModule.forRoot(config.foo)
            ],
            providers: [...]
        };
    }
}

...
imports: [FeatureModule.forRoot({ name: `ANOTHER_PREFIX` }), ...]
...

是否可以进行嵌套forRoot来电?

ModuleWithProviders似乎不接受imports

2 个答案:

答案 0 :(得分:1)

是的,你是对的。我们无法将imports传递给ModuleWithProviders导入。

以下是角度从这种导入中收集数据的方式:

} else if (importedType && importedType.ngModule) {
    const moduleWithProviders: ModuleWithProviders = importedType;
    importedModuleType = moduleWithProviders.ngModule;
    if (moduleWithProviders.providers) {
      providers.push(...this._getProvidersMetadata(
          moduleWithProviders.providers, entryComponents,
          `provider for the NgModule '${stringifyType(importedModuleType)}'`, [],
          importedType));
}

https://github.com/angular/angular/blob/4.3.x/packages/compiler/src/metadata_resolver.ts#L448-L456

我们可以通过在ModuleWithProviders.providers内传递相同的提供商来覆盖Ng2Webstorage.forRoot()内的提供商,如下所示:

import {Ng2Webstorage, WEBSTORAGE_CONFIG} from 'ngx-webstorage';

@NgModule({
  imports: [
    Ng2Webstorage.forRoot()
  ],
  ...
})
export class FeatureModule {
  static forRoot(config): ModuleWithProviders {
    return {
      ngModule: FeatureModule,
      providers: [
        { provide: WEBSTORAGE_CONFIG, useValue: config }
      ]
    };
  }
}

答案 1 :(得分:1)

可以通过在forRoot()中显式重新定义提供程序来实现。包中的其他元素可以按常规方式导入和导出。

请注意,我使用Array.concat()轻松链接了多个模块。

@NgModule({
    imports: [
        BarModule,
    ],
    exports: [
        Ng2Webstorage,
        FooModule,
        BarModule,
    ]
})
class FeatureModule {
    static forRoot(config): ModuleWithProviders {
        return {
            ngModule: FeatureModule,
            /* Explicitly redefine the providers from imported/exported modules. */
            providers: [].concat(
                Ng2Webstorage.forRoot({ prefix: config.name }).providers,
                FooModule.forRoot(config.foo).providers
            )
        };
    }
}

编辑:

使用AOT编译时,上述方法不起作用。相反,请对静态导出函数键入的参数使用以下变通办法,例如config

export function ng2WebstorageProviders(name: string) {
  return Ng2Webstorage.forRoot({ prefix: name }).providers;
}

export function fooProviders(foo: object) {
  return FooModule.forRoot(foo).providers;
}

@NgModule({
  imports: [
    BarModule,
  ],
  exports: [
    Ng2Webstorage,
    FooModule,
    BarModule,
  ]
})
class FeatureModule {
  static forRoot(config: {name: string, foo: object}): ModuleWithProviders {
    return {
      ngModule: FeatureModule,
      /* Explicitly redefine the providers from imported/exported modules. */
      providers: [
        ...ng2WebstorageProviders(config.name),
        ...fooProviders(config.foo)
      ]
    };
  }
}

供参考: