Angular 12 ViewChildren in ngFor directive causes ExpressionChangedAfterItHasBeenCheckedError

819 Views Asked by At

I've a parent component from which is possible to open various tab containing the child component This is a part of parent component:

....
<p-tabPanel header="{{tab.title}}" *ngFor="let tab of tabs; let i = index" [closable]="true">
    <app-child-tab [modules]="modules" [profile]="tab.body" (onProfileModified)="onProfileModified()">
    </app-cmup-tab>
</p-tabPanel>
....

in .ts:

export class ParentComponent implements onInit {
    @ViewChildren(ChildTabComponent) childTabsComponent: QueryList<ChildTabComponent>;
    tabs: any[] = [];
    ...

    ngOnInit() {
        tabs.push({title: 'First', body: firstObject});
        tabs.push({title: 'Second', body: secondObject});
        ...
    }

    onProfileModified() {
       ... do stuff ...
    }
}

The child is:

export class ChildTabComponent {
    @Input() profile: any;
}

Opening tabs from parent view, it appears the error:

ERROR Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked

Is there an error using ViewChildren?

EDIT: My problem is that in child component I set some modules boolean input values to show in checkbox but opening successive tab, the checkbox aren't correctly set. The first tab is properly set but the successive take the value of the first tab.

1

There are 1 best solutions below

0
On

I would say because the "tabs" collection is changing as you are pushing values this could be the issue.

<div *ngIf="tabs">
  <p-tabPanel header="{{tab.title}}" *ngFor="let tab of tabs; let i = index" [closable]="true">
      <app-child-tab [modules]="modules" [profile]="tab.body" (onProfileModified)="onProfileModified()">
      </app-cmup-tab>
  </p-tabPanel>
</div>

Then in your typescript file: -

    public tabs: any[] = null;
    ...

    ngOnInit() {
       let localTabs: any[] = [];
       localTabs.push({title: 'First', body: firstObject});
       localTabs.push({title: 'Second', body: secondObject});
        ...
       // We now give the component all the info at once
       this.tabs = localTabs; 
    }