angular - 传入的类型不是 ComponentType,它没有 'ɵcmp' 属性。路由未使用配置服务注入注入 AngularRouter
问题描述
我正在使用应用初始化程序在启动之前尝试从数据库中填充路由。它应该非常简单,但我收到了上面的错误,我不知道为什么。传入的类型不是 ComponentType,它没有 'ɵcmp' 属性。它似乎绘制了路线,控制台日志实际上有回复。只是当我单击链接或尝试直接路由到我的动态路由之一时它会失败。在我的应用程序模块上,我还设置了入口组件,并尝试在此处设置它们以取得良好的效果,但无济于事。
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
模板配置服务
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;
}
}
应用路由模块
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);
})
};
}
路由器接口 `
import { Component } from '@angular/core';
export interface RouteInterface {
routes: Array<[RouterInterface]>;
}
interface RouterInterface{
path: string;
comp: Component;
}
`
和我的模拟 json 数据库 `
[{
"path": "one",
"comp": "OneComponent"
},
{
"path": "two",
"comp": "TwoComponent"
},
{
"path": "three",
"comp": "ThreeComponent"
}]
`
解决方案
整个 app-routing.module.ts
import { APP_INITIALIZER, ComponentFactoryResolver, Injector, NgModule, ViewContainerRef } from '@angular/core';
import { Router, RouterModule, Routes, ɵEmptyOutletComponent } from '@angular/router';
import { retry } from 'rxjs/operators';
import { RouterInterface } from 'src/interfaces/route.interface';
import { OutletComponent } from './components/outlet/outlet.component';
import { OutletService } from './services/outlet.service';
import { TemplateConfigService } from './services/template-config.service';
const routes: Routes = [
{path: '', redirectTo: 'home', pathMatch: 'full'},
{path: 'home', component: OutletComponent}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [
TemplateConfigService, OutletService,
{ provide: APP_INITIALIZER, useFactory: configServiceFactory, deps: [Injector, TemplateConfigService, OutletService], multi: true },
]
})
export class AppRoutingModule {
constructor(private outletService: OutletService, private resolver: ComponentFactoryResolver){
outletService.subData$.subscribe((data) => {
data = data;
return data;
// sessionStorage.setItem('template', JSON.stringify(data));
});
// console.log('data', this.configService.configData)
}
}
// tslint:disable-next-line: ban-types
export function configServiceFactory(injector: Injector, configService: TemplateConfigService,
outletService: OutletService): any {
return async () => {
console.log('Getting config in routing module');
const res = await configService
// tslint:disable-next-line: no-shadowed-variable
.loadConfig().then((res) => {
res = res;
const router: Router = injector.get(Router);
// const componentItem = '';
// const instance = this.elRef.createComponent(componentFactory, 0).instance;
/** get and or set langkey */
const langKey = localStorage.getItem('langKey');
if (langKey === null) {
localStorage.setItem('langKey', 'us-english');
retry(2);
}
// tslint:disable-next-line: no-non-null-assertion
outletService.setViewportData(langKey!);
outletService.subData$.subscribe((data) => {
data = data;
return data;
// sessionStorage.setItem('template', JSON.stringify(data));
});
res.forEach((item$: RouterInterface) => {
console.log(item$);
const path$ = item$.path;
/** check if null or unknow and set variable langDefault */
// tslint:disable-next-line: no-non-null-assertion
// outletService.headerData$.subscribe((dat: any) => {
// const data$ = {
// dat$: dat
// };
router.config.unshift({path: path$,
component:
OutletComponent
});
console.log(router.config);
});
// });
router.resetConfig(router.config);
});
};
}
推荐阅读
- javascript - 如何读取 JavaScript 中内置的可迭代对象记录的值?
- python - 如何根据复杂的字符串列对数据框进行排序?
- symfony - 外部应用程序中的 Symfony Web 调试工具栏
- r - 地理加权套索 (pkg = gwrr) - Wi %*% X[-i, ] 中的错误:需要数字/复数矩阵/向量参数
- javascript - 加载时的 CSS 缩放效果 - 隐藏 DIV/图像加载延迟
- c# - Autofac - 解决服务中的具体实现
- reactjs - 如何将上下文一分为二
- c# - 用 itext 7 用动态内容填充动态 XFA 表单
- java - 如何在 Android Studio 中将 OpenCV Mat 输入帧转换为 Tensorflow 张量?
- python - 将单个请求组合成批量请求 API PYTHON