【问题标题】:Dynamically import modules into module based on `forRoot` config基于 `forRoot` 配置动态导入模块到模块中
【发布时间】:2021-10-22 04:17:45
【问题描述】:

我有一个使用AgmCoreModule 的模块。它将apiKey 应用于forRoot 并通过LAZY_MAPS_API_CONFIG 添加AgmCoreModule

...some_module.ts

export const AgmCoreModuleForRoot = AgmCoreModule.forRoot()


imports: [
 AgmCoreModuleForRoot,
]
providers: [
    {
      provide: LAZY_MAPS_API_CONFIG,
      useClass: GoogleMapsConfigService,
      deps: [GoogleMapsConfigServiceConfig],
    },
  ],

export class SomeModule {
  static forRoot(
    config?: GoogleMapsConfigServiceConfig,
  ): ModuleWithProviders<SomeModule> {
    return {
      ngModule: SomeModule,
      providers: [{ provide: GoogleMapsConfigServiceConfig, useValue: config }],
    };
  }
}

该模块主要由不需要AgmCoreModule 的组件组成,因此SomeModule 可以使用空白forRoot 导入,例如SomeModule.forRoot()

但是,我在使用 SomeModule 和在更高模块中导入了 AgmCoreModule 的应用程序时遇到了问题,例如 App.module。这会覆盖AgmCoreModuleforRoot

示例:

...app.module
imports:[
AgmCoreModule.forRoot({
      apiKey: environment.googleApiKey,
      libraries: ['places'],
    }),

...downstream.module.ts
imports: [
SomeModule.forRoot() <-- This overwrites the above apiKey making the google places api not work

我希望能够灵活地根据SomeModuleforRoot 中是否存在apiKey 来有条件地加载AgmCoreModule

这甚至是一件事吗?

【问题讨论】:

  • 你应该在每个应用程序中只使用一次 forRoot,最好是 AppModule 或 CoreModule 在其他情况下你只需要使用 SomeModule 而不调用 forRoot 的组件
  • SomeModule 可以在任何地方加载。它必须有一个 forRoot 才能将该数据传递给 Google 地方模块。
  • 嗯,你读过这个吗? angular-maps.com/api-docs/agm-core/modules/agmcoremodule "在根级别注册模块时请使用此方法。"你不需要在每个地方都使用 forRoot 你需要在根目录中使用 AgmCoreModule 通常 CoreModule 或 AppModule 在其他地方你使用该模块而不使用 forRoot
  • 请停止尝试重写用例...这个模块是一个外部库,我不知道AgmCoreModule是否被加载,在forRoot的存在之外在SomeModule

标签: angular angular-module


【解决方案1】:

我看不到您的AgmCoreModule,但您是否尝试过执行以下类似操作来防止重新导入核心模块?

// module-import.guard.ts
export function throwIfAlreadyLoaded(parentModule: any, moduleName: string) {
  if (parentModule) {
    throw new Error(`${moduleName} has already been loaded, import Core modules in the AppModule only.`);
  }
}

// agm-core.module.ts
export class AgmCoreModule{
  constructor(@Optional() @SkipSelf() parentModule: AgmCoreModule) {
    throwIfAlreadyLoaded(parentModule, 'AgmCoreModule');
  }
}

至于您的api 键覆盖情况,如果配置不存在,您能否不将其包装以返回其他内容?或者SomeModule 是否需要与 GoogleMapsConfigService 进行通信,如果不需要,那么下面的内容可能会对您有所帮助:

export class SomeModule {
  static forRoot(config?: GoogleMapsConfigServiceConfig): ModuleWithProviders<SomeModule> {
    
    if(config) {
      return {
        ngModule: SomeModule,
        providers: [{ provide: GoogleMapsConfigServiceConfig, useValue: config }],
      };
    }
    
    return {
      ngModule: SomeModule
    };
  }
}

【讨论】:

  • 我不想抛出错误。我想 SomeModule 从它的导入中删除 AgmCoreModule。小背景故事,SomeModule 是一个可发布的库。所以它并不总是知道apiKey
  • 我已经尝试了第二种方法。不幸的是,AgmCoreModule 键被 SomeModule 的存在覆盖,所以只返回 SomeModule 意味着没有 api 键。谷歌地图拒绝工作。
猜你喜欢
  • 2021-06-07
  • 2016-08-03
  • 2021-11-12
  • 2016-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-25
  • 2011-04-17
相关资源
最近更新 更多