1

I am using Angular 7 and use "ng serve" to launch the app. I have parent-child components and parent component has a button on click flips a boolean property value. if that boolean property is true child component is displayed (*ngIf). From the child component, I emit an event that calls the function in the parent which flips the boolean property value in Parent causing the child component to be removed (*ngIf)

Parent component:

Parent.component.ts

 capture: boolean = false;
  onCapture () {
    console.log("onCapture called")
    this.capture =  !this.capture;
  }

Parent.component.html

<app-capture *ngIf="capture ==true" (closeCapturePage)="onCapture()"></app-capture>
 <label>
    <img src="/assets/img/camera.svg" alt="" width="32" height="32" title="Open window">
    <input type="button" (click)="onCapture()" id="capture" style="display: none">
  </label>

Child-component.ts

@Output() closeCapturePage = new EventEmitter<void>();

closePage() {
      this.closeCapturePage.emit();
}

I can see the child component emits event successfully however encountering the error ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: false'. Current value: 'ngIf: true'

I tried the solutions suggested in similar threads such as implementing ngAfterViewChecked in parent component but no luck.

  show = false;

  ngAfterViewChecked(): void {
  let show = this.capture;
  if (show != this.show) {
    this.show = show;
    this.cdRef.detectChanges();
  }
  }

Stackblitz Example: https://stackblitz.com/edit/angular-8efhdm (NOTE: the simple example was not reproducing, so I added the actual code that start the camera but doesn't record anything, no privacy issues!)

javapedia.net
  • 2,531
  • 4
  • 25
  • 50

1 Answers1

1

Just in case someone is searching for an answer like I was. The solution I needed was understanding what the error was for:

https://indepth.dev/posts/1001/everything-you-need-to-know-about-the-expressionchang

And this bit of code to be applied when I knew the change was occurring.

I received the expressChangedAfterChecked because of this HTML code

<relation-mapping *ngIf="loadRelationMappings"
  [mappingPayload]="mappingPayload"
  [mappedRelationIndex]="mappedRelationIndex"
  (mappingPayloadEmitted)="onSentMappingPayload($event)"
  (mappedRelationIndexEmitted)="onSentRelationIndex($event)"
></relation-mapping>

And this change after the asynchronous call was made

this.LS.findAll('MappingPart2', 'master').subscribe( (mappingData: Collection) => {
      console.log('mappingData', mappingData);
      console.log('targetEntity', this.targetEntity);
      // find if class has mappings
      const list = mappingData._items.filter( (lc: Lifecycle) => lc._mapping._clazzReference._name === this.ES.targetNodePath[1].data.name);
      this.mappingPayload = list.length === 1 ? list[0] : null;
      // find if the class has a mapping for the relation the user is on
      if (!!this.mappingPayload) {
        this.loadRelationMappings = true;
        this.mappedRelationIndex = this.mappingPayload._mapping._mappedRelations.findIndex( (relationMapped: RelationMap) => relationMapped._name === this.ES.targetEntity._name);
        this.cd.detectChanges();
        if (this.mappedRelationIndex !== -1 ) {
          this.readRelations = this.mappingPayload._mapping._mappedRelations[this.mappedRelationIndex]._mappedRelationMappings;
        }
      }

      console.log('this.targetMapping', this.mappingPayload);
    });

Adding the this.cd.detectChanges() when I knew the variable/value was being updated fixed the problem for me.

Sankofa
  • 600
  • 2
  • 7
  • 19