2

My current component has the responsibility of performing two tasks, in chronological order:

  1. ngOnInit: Loop through data that was queried from a server, and insert a component for each part of the list.
  2. ngAfterViewInit: Subscribe to a @ViewChildren(MyDirective) changes observable and, on change, insert components dynamically.

The error I get is the following:

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: '0'. It seems like the view has been created after its parent and its children have been dirty checked. Has it been created in a change detection hook ?

It does seem to make sense, as I am creating components in a change detection hook.

My current code, simplified to a minimum example that throws the same error as my own:

Directive

@Directive({selector: '[min-insert]'})
export class MinDirective {
    @Input("min-insert") public minData;
    constructor(public viewContainerRef: ViewContainerRef) { }
}

Component (The important part here is not the exact code, but that a component gets created on subscription change.)

...
someData : any;
@ViewChildren(MinDirective)d:QueryList<MinDirective>;
ngOnInit(){
    this.service.doHTTPStuff(...); //Assigns real data to "someData"
}
ngAfterViewInit(){
    this.d.changes.subscribe(()=> {this.d.forEach(dir=>{
        let cF = this.componentService.getComponentFactory(...);
        dir.viewContainerRef.clear();
 (<IC>dir.viewContainerRef.createComponent(cF).instance).setData(dir.minData);

    })});
}

And here's the template, which has the "interesting" part for this error, I guess:

<div *ngFor="let minData of someData">
    <ng-template [min-insert]="minData"></ng-template>
</div>

Basically, the first thing that should happen, is that someData gets looped through, and for each minData in it, an empty shell for my directive gets created. Once I'm thus successfully able to fetch the directives with @ViewChildren, I want to "replace" them by creating a component on them.

If I remove the for-loop and only make one "empty shell" in a manner that I do not need to subscribe to @ViewChildren, everything works perfectly. The combination of both, however, outputs the error above.

Any ideas? Thanks!

user2065501
  • 99
  • 2
  • 9

0 Answers0