I am using an app initializer to try and populate the routes from a database prior to launch. it should be very straightforward but I am getting the error above and I am not sure why. The type passed in is not ComponentType, it does not have 'ɵcmp' property. it appears to draw the routes and the console log actually has a reply. it's just when I click a link or try to route directly to one of my dynamic routes it fails. on my app module, I also have the entry components set and tried to set them here as well for good measure but to no avail.
Angular Info:
Angular CLI: 11.1.4
Node: 14.7.0
OS: darwin x64
Angular: 11.1.2
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Ivy Workspace: Yes
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1101.4
@angular-devkit/build-angular 0.1101.4
@angular-devkit/core 11.1.4
@angular-devkit/schematics 11.1.4
@angular/cli 11.1.4
@schematics/angular 11.1.4
@schematics/update 0.1101.4
rxjs 6.6.3
typescript 4.1.3
Template Config Service
import { RouteInterface } from './../../interfaces/route.interface';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class TemplateConfigService {
// tslint:disable-next-line: variable-name
private _configData ?: RouteInterface;
// tslint:disable-next-line: variable-name
private _promise ?: Promise<any>;
// tslint:disable-next-line: variable-name
private _promiseDone = false;
constructor(private http: HttpClient) { }
loadConfig(): Promise<any> {
console.log('started')
const url = '/assets/json/config/route.config.json';
if (this._promiseDone) {
console.log('In Config Service. Promise is already complete.');
return Promise.resolve();
}
if (this._promise != null) {
console.log('In Config Service. Promise exists. Returning it.');
return this._promise;
}
console.log('In Config Service. Loading config data.');
this._promise = this.http
.get(url, { headers: new HttpHeaders() }).pipe(
// map((res: Response) => res))
map((res: any) => {
res = res;
return res
})
)
.toPromise()
.then((res: any) => {
// console.log(res)
this._configData = res; this._promiseDone = true; return this._configData})
.catch((err: any) => { this._promiseDone = true; return Promise.resolve(); });
return this._promise;
}
get configData(): any {
console.log('should be interface', this._configData)
return this._configData;
}
}
AppRouting Module
import { HomeComponent } from './components/home/home.component';
import { TemplateConfigService } from './services/template-config.service';
import { APP_INITIALIZER, Component, ComponentDecorator, ComponentFactoryResolver, Injector, NgModule, Type } from '@angular/core';
import { Router, RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{path: '', redirectTo: 'home', pathMatch: 'full'},
{path: 'home', component: HomeComponent}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [
TemplateConfigService,
{ provide: APP_INITIALIZER, useFactory: configServiceFactory, deps: [Injector, TemplateConfigService], multi: true },
]
})
export class AppRoutingModule {
constructor(){
// console.log('data', this.configService.configData)
}
}
// tslint:disable-next-line: ban-types
export function configServiceFactory(injector: Injector, configService: TemplateConfigService): Function {
return async () => {
console.log('Getting config in routing module');
const res = await configService
.loadConfig().then((res)=>{
res = res;
const router: Router = injector.get(Router);
res.forEach(
(item: any) => {
console.log(item)
router.config.unshift({path: item.path, component: item.comp as Type<Component>})
console.log('router-config', router.config);
});
router.resetConfig(router.config);
})
};
}
router interface `
import { Component } from '@angular/core';
export interface RouteInterface {
routes: Array<[RouterInterface]>;
}
interface RouterInterface{
path: string;
comp: Component;
}
`
and my mock json database `
[{
"path": "one",
"comp": "OneComponent"
},
{
"path": "two",
"comp": "TwoComponent"
},
{
"path": "three",
"comp": "ThreeComponent"
}]
`
I ended up using a generic component called outlet.
`
`
no matter what resolver i use it doesn't work any other way. maybe someday someone can come up with a different work around - but I'm not spending any more cycles on this it will work the way i need it to work.