![](/img/trans.png)
[英]Angular Dynamic Components and ExpressionChangedAfterItHasBeenCheckedError
[英]Angular ExpressionChangedAfterItHasBeenCheckedError inside Dynamic Components
我将针对不同的语句动态解析组件。
所以,我为它创建了一个指令和一个组件。
import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[mcmsDynamicHost]'
})
export class DynamicHostDirective {
constructor(
public viewContainerRef: ViewContainerRef
) { }
}
import { AfterViewInit, Component, ComponentFactoryResolver, Input, ViewChild } from '@angular/core';
import { DynamicHostDirective } from '@mcms/ui-kit/dynamic-host/dynamic-host.directive';
@Component({
selector: 'mcms-dynamic-host',
templateUrl: './dynamic-host.component.html',
styleUrls: ['./dynamic-host.component.scss']
})
export class DynamicHostComponent implements AfterViewInit {
@ViewChild(DynamicHostDirective) dynamicHost: DynamicHostDirective;
@Input() component;
constructor(
private componentFactoryResolver: ComponentFactoryResolver
) { }
ngAfterViewInit(): void {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.component);
const viewContainerRef = this.dynamicHost.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory);
}
}
// component template
<ng-template mcmsDynamicHost></ng-template>
现在我正在以这种方式使用它们。
<div *ngFor="let item of dashboard">
<mcms-dynamic-host [component]="item.card"></mcms-dynamic-host>
</div>
this.dashboard = [
{cols: 2, rows: 3, y: 0, x: 0, dragEnabled: true, card: WelcomeCardComponent, title: 'Welcome to Municipal CMS!'},
{cols: 1, rows: 3, y: 0, x: 2, dragEnabled: true, card: SiteResumeCardComponent, title: 'Site Resume'},
{cols: 2, rows: 5, y: 3, x: 0, dragEnabled: true, card: TrafficActivityCardComponent, title: 'Traffic activity'},
];
静态组件的渲染没有任何问题。 但是如果我尝试将一些值绑定到动态解析组件中的模板,例如 *ngFor 甚至 *ngIf,都会抛出错误 - ExpressionChangedAfterItHasBeenCheckedError
但是当我做这个把戏时,
ngOnInit(): void {
setTimeout(() => {
this.data = [
{ image: 'assets/images/green-icons/page-small.svg', title: 'Pages', count: 5 },
{ image: 'assets/images/green-icons/user-small.svg', title: 'Active Users', count: 7 },
{ image: 'assets/images/green-icons/blog-small.svg', title: 'Blog Post', count: 12, pending: 3 },
{ image: 'assets/images/green-icons/comment-small.svg', title: 'Comments', count: 54, pending: 8 },
{ image: 'assets/images/green-icons/media-small.svg', title: 'Digital Assets', count: 230 },
];
}, 100);
}
没有错误。 这对我来说有点奇怪,无论如何我们都可以这样做,但是当我尝试使用例如@angular/material 组件时,就没有办法做这种把戏。
任何人都遇到过类似的问题?
这里是 stackblitz 链接 - https://stackblitz.com/edit/angular-kf3pdw
尝试将数据分配移动到ngAfterViewInit
生命周期钩子而不是ngOninit
顺便说一句,动态组件加载通常应该使用CDK Portal来完成
我的代码有一个愚蠢的错误。 使用 Angular v9,@ViewChild 装饰器静态标志默认为false
。 这意味着在更改检测运行后解析查询结果。 为了在更改检测运行之前解析查询结果,它应该是true
。
Stackblitz 更新了正确答案。 希望这个经验可以帮助其他人! 干杯!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.