我需要在启动时基于主机名在Angular应用程序中使用单独的路由。为此,我创建了一个单独的服务TenantService以获取租户。接下来,我创建了另一个名为AppRoutingService的服务,该服务具有根据TenantService的响应创建路由的功能。该功能需要在应用程序启动时执行,并相应地编辑应用程序路由。
以下是我收到的错误,接下来是代码段:
Getting cyclic dep error
compiler.js:10477 Uncaught Error: Provider parse errors:
Cannot instantiate cyclic dependency! ApplicationRef ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1
at NgModuleProviderAnalyzer.parse (compiler.js:10477)
at NgModuleCompiler.compile (compiler.js:20607)
at JitCompiler._compileModule (compiler.js:25606)
at compiler.js:25567
at Object.then (compiler.js:2166)
at JitCompiler._compileModuleAndComponents (compiler.js:25565)
at JitCompiler.compileModuleAsync (compiler.js:25527)
at CompilerImpl.compileModuleAsync (platform-browser-dynamic.js:216)
at compileNgModuleFactory__PRE_R3__ (core.js:34647)
at PlatformRef.bootstrapModule (core.js:34956)
代码如下:
AppModule
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { RouterModule } from "@angular/router";
import { AppComponent } from './app.component';
import { TenantService } from './tenant/tenant.service';
import {AppRoutingService} from './app-routing.service';
export function initSettings(appRoutingService: AppRoutingService) {
return () => appRoutingService.initializeRoutes();
}
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
RouterModule.forRoot([])
],
providers: [TenantService,
AppRoutingService,
{
provide : APP_INITIALIZER,
useFactory : initSettings,
deps : [AppRoutingService],
multi : true
}],
bootstrap: [AppComponent]
})
export class AppModule { }
AppRoutingService
import { Injectable } from '@angular/core';
import {TenantService, Tenant } from './tenant/tenant.service';
import { Routes, Router } from '@angular/router';
import { from } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AppRoutingService {
constructor(private router: Router, private tenantService: TenantService) { }
initializeRoutes(): Promise<any> {
return new Promise((resolve, reject) => {
let appRoutes: Routes = [];
if (this.tenantService.getTenant() === Tenant.CLIENT1) {
console.log('Configuring CLIENT1 Login Components.');
appRoutes = [
{ path: 'hotel-list', loadChildren: () => import('./hotel/hotel.module').then(m => m.HotelModule) },
{ path: '', redirectTo: 'hotel-list', pathMatch: 'full'}
];
appRoutes.forEach(e => this.router.config.unshift(e));
resolve(true);
} else if (this.tenantService.getTenant() === Tenant.CLIENT2) {
console.log('Configuring CLIENT2 Login Components.');
appRoutes = [
{ path: 'natgeo-list', loadChildren: () => import('./natgeo/natgeo.module').then(m => m.NatgeoModule) },
{ path: '', redirectTo: 'natgeo-list', pathMatch: 'full'}
];
appRoutes.forEach(e => this.router.config.unshift(e));
resolve(true);
} else {
reject(false);
}
});
}
}
TenantService
import { Injectable } from '@angular/core';
import { HttpHeaders } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class TenantService {
constructor() {}
getTenantForHostname(hostname: string): Tenant {
return this.getTenantForHost(hostname.split('.')[0]);
}
getTenantForString(s: string) {
for (const e in Tenant) {
if (e.toLowerCase() === s.toLowerCase()) {
return Tenant[e] as Tenant;
}
}
return null;
}
getTenantForHost(host: string): Tenant {
return this.getTenantForString(host);
}
getTenant(): Tenant {
return this.getTenantForHostname(location.hostname);
}
addTenantToHeaders(headers: HttpHeaders): HttpHeaders {
return headers.append('X-Tenant-ID', this.getTenant());
}
}
export enum Tenant {
CLIENT1 = 'hotel',
CLIENT2 = 'natgeo'
}
感谢您为纠正错误提供的任何帮助。另外,也欢迎您使用一种替代方法来满足我的要求。
答案 0 :(得分:2)
只需使用Injector
来获取Router
并将其重置。
Stackblitz:https://stackblitz.com/github/hsuanxyz/ng-dynamic-routes-config
Github存储库https://github.com/hsuanxyz/ng-dynamic-routes-config
tenant.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class TenantService {
getTenant() {
return true;
}
}
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { APP_INITIALIZER, Injector, NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { TenantService } from './tenant.service';
import { Router } from '@angular/router';
export function initSettings(injector: Injector, tenantService: TenantService) {
return () => new Promise(resolve => {
let routes = [];
if (tenantService.getTenant()) {
routes = [
{ path: 'hotel-list', loadChildren: () => import('./hotel/hotel.module').then(m => m.HotelModule) },
{ path: '', redirectTo: 'hotel-list', pathMatch: 'full' }
];
} else {
routes = [
{ path: 'natgeo-list', loadChildren: () => import('./natgeo/natgeo.module').then(m => m.NatgeoModule) },
{ path: '', redirectTo: 'natgeo-list', pathMatch: 'full' }
];
}
const router: Router = injector.get(Router);
router.resetConfig(routes);
resolve();
});
}
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [
TenantService,
{
provide : APP_INITIALIZER,
useFactory : initSettings,
deps : [Injector, TenantService],
multi : true
}
],
bootstrap: [AppComponent]
})
export class AppModule { }