Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expression has changed after it was checked - MatDialog Angular 6

I have read several answers, and I have tried many but I can't seem to get this to work. In my angular 6 app, I try to open a MatDialog but I receive this error:

ERROR Error:
ExpressionChangedAfterItHasBeenCheckedError:
Expression has changed after it was checked. Previous value: '@slideDialog: enter'. Current value: '@slideDialog: exit'.

When I debug the app and click the checkout button, the MatDialog opens and then after stepping through a few more lines it closes. When running the app without breakpoints, you never see the dialog open at all.

Here is the template file:

<div>
  <button id="cancelButton" mat-raised-button (click)="clearCart()">Cancel</button>
  <button id="checkoutButton" mat-raised-button color="primary" (click)="openCheckoutDialog(dataSource)" [disabled]="isTableEmpty()">Checkout</button>
</div>

When I click the button with the id "checkoutButton" it calls openCheckoutDialog()

Here is my class where openCheckoutDialog is called:

import { Component, OnInit, ChangeDetectorRef  } from '@angular/core';

@Component({
  selector: 'app-shopping-cart',
  templateUrl: './shopping-cart.component.html',
  styleUrls: ['./shopping-cart.component.css']
})
export class ShoppingCartComponent implements OnInit {

  dataSource: MatTableDataSource<Item>;
  itemList: Item[] = [];

  constructor(public dialog: MatDialog, private cdr: ChangeDetectorRef) { }

  openCheckoutDialog(): void {
    const dialogRef = this.dialog.open(ReviewItemListComponent, {
      width: '250px',
      data: this.itemList
    });
    // this.cdr.detectChanges();

    dialogRef.afterClosed().subscribe(result => {
      console.log(`Dialog result: ${result}`);
    });
    // this.cdr.detectChanges();
  }
}

I have tried the this.cdr.detectChanges() in those 2 places above, but I would still receive the error.

Here is my ReviewItemListComponent template (dialog when the checkout button is clicked):

<div>
  <h1 mat-dialog-title>
    Are you sure?
  </h1>

  <mat-dialog-actions>
    <button tabindex="-1" mat-raised-button [mat-dialog-close]="true">Cancel</button>
    <button tabindex="-1" mat-raised-button color="primary" (click)="confirm()">Confirm</button>
  </mat-dialog-actions>
</div>

And here is the ReviewItemListComponent class:

import { Component, OnInit, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { Item } from '../item';

@Component({
  selector: 'app-review-item-list',
  templateUrl: './review-item-list.component.html',
  styleUrls: ['./review-item-list.component.css']
})
export class ReviewItemListComponent implements OnInit {

  constructor(public dialogRef: MatDialogRef<ReviewItemListComponent>,
    @Inject(MAT_DIALOG_DATA) public data: Item[]) { }

  ngOnInit() {
    this.dialogRef.close();
  }

  confirm(): void {
    this.dialogRef.close();
  }

}

I'm not making any changes to data, which is what most of the questions & answers involve, so how do I resolve this problem regarding opening a MatDialog?

Edit:

Turns out I had pasted this.dialogRef.close() into the wrong method. In this case I put it inside of ngOnInit() when I was creating my review-item-list-component.ts file. So once I open it I close it. This still doesn't explain the error. What is so wrong about closing the recently opened dialog inside of ngOnInit()?

like image 936
Michael Avatar asked Jul 11 '18 17:07

Michael


People also ask

How do you fix expression has changed after it was checked?

Navigate up the call stack until you find a template expression where the value displayed in the error has changed. Ensure that there are no changes to the bindings in the template after change detection is run. This often means refactoring to use the correct component lifecycle hook for your use case.


2 Answers

Use dialog close inside settimeout.

setTimeout(() => {    
    this.dialogRef.close();
}, 0);
like image 142
Manoj Sanjeewa Avatar answered Sep 23 '22 08:09

Manoj Sanjeewa


Change [mat-dialog-close] or [matDialogClose] to (click) event. That's works for me.

I guess [matDialogClose] is now working as we expected.

like image 37
Aarón Cervantes Avatar answered Sep 23 '22 08:09

Aarón Cervantes