Angular 8,如何将配置传递给懒加载的模块

3
我需要将提供者传递给延迟加载的模块。 上下文: 我有一个模块,用于访问 API 并返回一些配置以在组件中呈现。 这是该模块:
@NgModule({
  declarations: [AuxTablesComponent, AuxTablesListingComponent],
  providers: [AuxTablesService, AuxTableDataResolverGuard],
  imports: [CommonModule, AuxTablesRoutingModule, SharedModule]
})
export class AuxTablesModule {}

在另一个模块中作为延迟加载(Lazy)导入:

const routes: Routes = [
      {
        path: AIRPORTS_ROUTES.AUX_TABLES.route,
        loadChildren: () => import('./aux-tables/aux-tables.module').then(m => m.AuxTablesModule)
      }
      ...
    ]
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class AirportsRoutingModule {}

这个功能非常好用。但我现在需要在另一个模块中使用完全相同的模块、视图和行为,但我需要更改负责从另一个API获取数据的提供程序。因此,我想更改AuxTablesService和AuxTableDataResolverGuard。

我尝试做这样的事情:将其导入到另一个模块中,例如TrainsModule。

const routes: Routes = [
      {
        path: TRAINS.AUX_TABLES.route,
        loadChildren: () => import('./aux-tables/aux-tables.module').then(m => m.AuxTablesModule
        .forChild(newApiProvider, newResolverGuard))
      }
      ...
    ]
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class TrainsRoutingModule {}

并准备AuxTablesModule来接收自定义提供程序,如下所示:

@NgModule({
  declarations: [AuxTablesComponent, AuxTablesListingComponent],
  providers: [AuxTablesService, AuxTableDataResolverGuard],
  imports: [CommonModule, AuxTablesRoutingModule, SharedModule]
})
export class AuxTablesModule {
  static forChild(auxTableApiService: AuxTablesService, auxTableGuardResolver: Resolve<IAuxTable>) {
    return {
      ngModule: AuxTablesModule,
      providers: [
        {
          provide: AuxTablesService,
          useClass: auxTableApiService
        },
        {
          provide: AuxTablesService,
          useClass: auxTableGuardResolver
        }
      ]
    };
  }
}

但是当Angular尝试渲染forChild懒加载模块时,我收到了以下错误:

core.js:6014 ERROR Error: Uncaught (in promise): Error: No NgModule metadata found for '[object Object]'。

调试Angular时,返回的Object不是构造函数,不能将其作为模块进行“工厂化”,也无法在其上找到@ngModule的元数据。有人知道如何做到这一点吗?例如向懒加载的模块提供自定义类?


我认为你正在寻找FactoryProviders:https://stackoverflow.com/a/60304854/6455844 - Max K
不行 :/,我可以将提供者更改为factoryProvider,这样就没问题了,但问题是作为LazyLoaded模块导入时,我无法使用任何配置实例化该模块。 - Gustavo Vieira
我找到了一个解决方法,但似乎不是正确的设计模式。 我已经从想要延迟加载的模块中删除了提供程序。 并在延迟加载模块的调用模块上传递提供程序,因此基本上,延迟加载的模块查找提供程序并找不到它,所以从调用模块获取它。但这似乎不正确,我真的希望我的模块有自己的提供程序,并且能够在需要时覆盖原始提供程序进行延迟加载。 - Gustavo Vieira
2个回答

0

嗯,我找到了一个解决方法,但似乎不太对。

我从想要进行懒加载的模块中移除了提供者。

现在变成了这样:

@NgModule({
  declarations: [AuxTablesComponent, AuxTablesListingComponent],
  imports: [CommonModule, AuxTablesRoutingModule, SharedModule]
})
export class AuxTablesModule {}

然后我将提供者传递给每个延迟导入它的模块:

@NgModule({
  declarations: [
   ...
  ],
  providers: [
    {
      provide: AuxTablesService,
      useClass: TrainsAuxTablesService
    },
    {
      provide: AuxTableDataResolverGuard,
      useClass: TrainAuxTableResolverGuard
    }
    ...
  ],
  imports: [...],
})
export class TrainsModule {}

并且:

@NgModule({
  declarations: [
   ...
  ],
  providers: [
    {
      provide: AuxTablesService,
      useClass: AirPortsAuxTablesService
    },
    {
      provide: AuxTableDataResolverGuard,
      useClass: AirPortsAuxTableResolverGuard
    }
    ...
  ],
  imports: [...],
})
export class AirPortsModule {}

所以,延迟加载的模块寻找自身的提供者,但找不到。它会寻找其父模块,并找到它,这样它就可以通过父模块注入提供者进行实例化。
但我真的希望我的模块有自己的提供者,并在延迟加载时被覆盖。

0
自从Angular 14版本以后,你可以在路径中添加提供者。
const routes: Routes = [
  {
    path: AIRPORTS_ROUTES.AUX_TABLES.route,
    loadChildren: () => import('./aux-tables/aux-tables.module').then(m => m.AuxTablesModule),
    providers: [{ provide: SomeService, useClass: MySomeService }]
  }
  ...
];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接