1. ホーム
  2. angular

[解決済み] ExpressionChangedAfterItHasBeenCheckedError: チェックされた後に、式が変更されました。以前の値: 'undefined'

2022-10-10 19:09:20

質問

同じ質問がすでにstack-overflowにたくさん投稿されていることは知っていますし、ランタイムエラーを回避するためにさまざまな解決策を試しましたが、どれも私にはうまくいきません。

コンポーネントとHTMLコード

export class TestComponent implements OnInit, AfterContentChecked {
    @Input() DataContext: any;
    @Input() Position: any;
    sampleViewModel: ISampleViewModel = { DataContext: : null, Position: null };
    constructor(private validationService: IValidationService, private modalService: NgbModal, private cdRef: ChangeDetectorRef) {
    }

    ngOnInit() {

    }
    ngAfterContentChecked() {

            debugger;
            this.sampleViewModel.DataContext = this.DataContext;
            this.sampleViewModel.Position = this.Position;

    }


<div class="container-fluid sample-wrapper text-center" [ngClass]="sampleViewModel.DataContext?.Style?.CustomCssClass +' samplewidget-'+ sampleViewModel.Position?.Columns + 'x' + sampleViewModel.Position?.Rows">
     //some other html here
</div>

注意:このコンポーネントはDynamicComponentLoaderを使用して動的にロードされます。

トラブルシューティングの結果、いくつかの問題があることがわかりました。

まず、この子コンポーネントは DynamicComponentResolver を使用して動的に読み込まれ、以下のように入力値を渡します。

 ngAfterViewInit() {
    this.renderWidgetInsideWidgetContainer();

  }


  renderWidgetInsideWidgetContainer() {
    let component = this.storeFactory.getWidgetComponent(this.dataSource.ComponentName);
    let componentFactory = this._componentFactoryResolver.resolveComponentFactory(component);
    let viewContainerRef = this.widgetHost.viewContainerRef;
    viewContainerRef.clear();
    let componentRef = viewContainerRef.createComponent(componentFactory);
    debugger;
    (<IDataBind>componentRef.instance).WidgetDataContext = this.dataSource.DataContext;
    (<IDataBind>componentRef.instance).WidgetPosition = this.dataSource.Position;

  }

子コンポーネントのhtmlを以下のように変更しても同じエラーが発生します。ただ、angular ngclass属性を追加してください。

<div class="container-fluid ds-iconwidget-wrapper text-center" [ngClass]="Sample">

</div>

データバインディングもすべてうまくいっているのですが、親コンポーネントで何かする必要がありますか? 私はすでに子コンポーネントですべてのライフサイクルイベントを試してみました。

どのように解決するのですか?

この ngAfterContentChecked のライフサイクルフックは、子コンポーネントやディレクティブのバインディングの更新がすでに終了しているときに起動されます。しかし、バインディングの入力として使用されるプロパティを更新しているのは ngClass ディレクティブのバインディング入力として使われるプロパティを 更新しています。これが問題なのです。Angularが検証ステージを実行すると、プロパティに保留中の更新があることが検出され、エラーがスローされます。

このエラーをよりよく理解するために、以下の2つの記事を読んでください。

のプロパティを変更する必要がある理由を考えてみましょう。 ngAfterViewInit のライフサイクルフックを変更する必要があるのか考えてみましょう。の前にトリガーされる他のライフサイクルは、すべて ngAfterViewInit/Checked の前にトリガーされる他のライフサイクルは動作します。 ngOnInit または ngDoCheck または ngAfterContentChecked .

というわけで、これを修正するために renderWidgetInsideWidgetContainerngOnInit() のライフサイクルフックに追加します。