Angular 9 使用 viewContainerRef 加载动态组件得到未定义的结果
Angular 9 Load Dynamic components with viewContainerRef gets undefined result
我创建了一个在视图中使用视图的应用程序,我无法将我的代码移动到库中,然后共享代码。
我的主页使用带有 loadChildren() 的路由,然后实际加载要查看的组件。我的页面都共享一个通用的导航组件,该组件通过监视可观察对象提供标题栏、侧面菜单、自动隐藏、调整大小等。
因此,我的路由的主要路径是 NavigationComponent,它是简单的 Angular Material 导航示意图。然后它有一个 router-outlet,然后将显示我的目标组件。
我的主要页面是 Material 仪表板示意图。这些显示卡中包含信息并路由到标准 URL 以加载实际组件。
例如,我的主页有导航,然后是一系列卡片来显示不同的数据(关于网站、活动、新闻等)
const routes:Routes = [
{ path: '', component: NavigationCommonComponent,
children: [
{ path: '', component: HomeComponent },
{ path: 'aboutus', component: AboutComponent },
{ path: 'events', component: EventsComponent },
{ path: 'news', component: NewsComponent },
]
}
];
上面的基本路由可以提供一些信息。当这些只是卡片时,一切正常。我已经把卡片搬进了图书馆,数据可以显示在卡片上了。我现在要做的,实际上是在卡片数据中显示组件的内容。
例如,如果卡是硬编码的,您将使用
<mat-card>
<appEvents></AppEvents>
</mat-card>
这将使用 EventsController 来显示卡片中的任何内容。硬编码,这有效。我现在要做的是使用 Angular 9 个文档中相同的 viewComponentRef 示例,以便动态加载这些卡片。
例如,我现在有一个数据数组,其中的组件 (Type) 作为要查看的项目。我有一个卡片组件
我使用了示例中的 AdService:
@Injectable()
export class AdService {
public getAds() {
return [
new AdItem(HeroJobAdComponent, {name: 'Bombasto', bio: 'Brave as they come'}),
new AdItem(HeroJobAdComponent, {name: 'Dr IQ', bio: 'Smart as they come'}),
];
}
}
HeroJobAdComponent
@Component({
template: `
<div class="job-ad">
<h4>{{data.headline}}</h4>
{{data.body}}
</div>
`
})
export class HeroJobAdComponent implements AdComponent {
@Input() public data:any;
}
和提供的指令。
@Directive({
selector: '[appAdHost]',
})
export class AdDirective {
constructor(public viewContainerRef:ViewContainerRef) { }
}
一切似乎都是正确的,除了代码是 运行,来自 ViewChild 的 viewContainerRef:
@ViewChild(AdDirective, {static: true, read: ViewContainerRef}) public adHost:AdDirective;
在 const viewContainerRef = this.adHost.viewContainerRef;
行中似乎为空。 adHost 未定义。
public loadComponent() {
this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length;
const adItem = this.ads[this.currentAdIndex];
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);
const viewContainerRef = this.adHost.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory);
(componentRef.instance as AdComponent).data = adItem.data;
}
我认为这与组件的级别有关,我将 grid/card 列表(material 仪表板示意图)作为导航组件的 child。我不知道如何让这个元素不被定义。
删除 read: ViewContainerRef
属性。
我创建了一个在视图中使用视图的应用程序,我无法将我的代码移动到库中,然后共享代码。
我的主页使用带有 loadChildren() 的路由,然后实际加载要查看的组件。我的页面都共享一个通用的导航组件,该组件通过监视可观察对象提供标题栏、侧面菜单、自动隐藏、调整大小等。
因此,我的路由的主要路径是 NavigationComponent,它是简单的 Angular Material 导航示意图。然后它有一个 router-outlet,然后将显示我的目标组件。
我的主要页面是 Material 仪表板示意图。这些显示卡中包含信息并路由到标准 URL 以加载实际组件。
例如,我的主页有导航,然后是一系列卡片来显示不同的数据(关于网站、活动、新闻等)
const routes:Routes = [
{ path: '', component: NavigationCommonComponent,
children: [
{ path: '', component: HomeComponent },
{ path: 'aboutus', component: AboutComponent },
{ path: 'events', component: EventsComponent },
{ path: 'news', component: NewsComponent },
]
}
];
上面的基本路由可以提供一些信息。当这些只是卡片时,一切正常。我已经把卡片搬进了图书馆,数据可以显示在卡片上了。我现在要做的,实际上是在卡片数据中显示组件的内容。
例如,如果卡是硬编码的,您将使用
<mat-card>
<appEvents></AppEvents>
</mat-card>
这将使用 EventsController 来显示卡片中的任何内容。硬编码,这有效。我现在要做的是使用 Angular 9 个文档中相同的 viewComponentRef 示例,以便动态加载这些卡片。
例如,我现在有一个数据数组,其中的组件 (Type) 作为要查看的项目。我有一个卡片组件
我使用了示例中的 AdService:
@Injectable()
export class AdService {
public getAds() {
return [
new AdItem(HeroJobAdComponent, {name: 'Bombasto', bio: 'Brave as they come'}),
new AdItem(HeroJobAdComponent, {name: 'Dr IQ', bio: 'Smart as they come'}),
];
}
}
HeroJobAdComponent
@Component({
template: `
<div class="job-ad">
<h4>{{data.headline}}</h4>
{{data.body}}
</div>
`
})
export class HeroJobAdComponent implements AdComponent {
@Input() public data:any;
}
和提供的指令。
@Directive({
selector: '[appAdHost]',
})
export class AdDirective {
constructor(public viewContainerRef:ViewContainerRef) { }
}
一切似乎都是正确的,除了代码是 运行,来自 ViewChild 的 viewContainerRef:
@ViewChild(AdDirective, {static: true, read: ViewContainerRef}) public adHost:AdDirective;
在 const viewContainerRef = this.adHost.viewContainerRef;
行中似乎为空。 adHost 未定义。
public loadComponent() {
this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length;
const adItem = this.ads[this.currentAdIndex];
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);
const viewContainerRef = this.adHost.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory);
(componentRef.instance as AdComponent).data = adItem.data;
}
我认为这与组件的级别有关,我将 grid/card 列表(material 仪表板示意图)作为导航组件的 child。我不知道如何让这个元素不被定义。
删除 read: ViewContainerRef
属性。