3
votes

I have a question about mat-selection-list and reactive forms. The problem is that I create mat-selection list and then after I read from the local storage I update my form. Everything works but I get ExpressionChangedAfterItHasBeenCheckedError because it has obviously been created with default values. Is this expected behavior and how can I fix it if it is :)

you can see stack blitz example here:
https://stackblitz.com/edit/angular-ul58q4

2

2 Answers

3
votes

this error is because you set the form initial value but view can't detect it, so by using changeDetectorRef after set the initial value it will be right:

import { Component, AfterViewInit, Injectable ,ChangeDetectorRef } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { LocalStorageService } from './local-storage.service';

const FILTER_FORM_STORAGE_KEY = 'filterFormStorageKey';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
  formGroup: FormGroup;
  typesControl: FormControl;

  types: any[] = [
    { id: 1, name: 'Type A' },
    { id: 2, name: 'Type B' }
  ];

  constructor(private _storage: LocalStorageService,
  private changeDetectorRef: ChangeDetectorRef) {
    this.formGroup = new FormGroup({
      typesControl: this.typesControl = new FormControl(null, [Validators.required])
    });
  }

  ngAfterViewInit(): void {
    const formStorage = this._storage.get(FILTER_FORM_STORAGE_KEY);
    if (formStorage) {
      this.formGroup.patchValue(formStorage);
    }
    this.changeDetectorRef.detectChanges();
  }

  saveForm() {
    console.log('submitted');
    this._storage.set(FILTER_FORM_STORAGE_KEY, this.formGroup.value);   
  }
}

working DEMO.

1
votes

We can't able to view the source code in stackblitz. The issue is you are updating the component object after DOM has been updated. You need to manually trigger the change detection to update DOM as well. use

setTimeout(()=>{

}, 0);