簡體   English   中英

動態組件中的 Angular 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 更新了正確答案。 希望這個經驗可以幫助其他人! 干杯!

https://angular.io/api/core/ViewChild#description

https://angular.io/guide/static-query-migration

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM