Expression has changed after it was checked - MatDialog Angular 6
Asked Answered
O

3

11

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()?

Olwen answered 11/7, 2018 at 17:19 Comment(6)
Odd - those are animation props. Check that the library is compatible with NG6.Laceylach
There was a fairly recent issue filed for something very similar to this. Which I believe is actually related to this issue. The work-around seems to be to wrap your dialog creation in a setTimeoutDistillate
@Laceylach Check the edit section of my questionOlwen
@Und3rTow I've tried timeouts, check out my edited questionOlwen
There is nothing inherently wrong with closing the dialog in ngOnInit. The problem is that the view (dialog) is being modified during the change detection cycle.(which runs twice in dev mode - in prod you would not have this error) If you move dialog.close() into ngAfterViewInit I believe it should stop that error from being thrown.Distillate
99% of ExpressionChangedAfterItHasBeenCheckedError can be worked-around adding changeDetectionRef.detectChanges() on the parent.Biyearly
W
7

Use dialog close inside settimeout.

setTimeout(() => {    
    this.dialogRef.close();
}, 0);
Wayzgoose answered 2/12, 2019 at 8:21 Comment(0)
F
2

I know, that your question can already be not actual, but anyway I will answer. The problem is that you call close method in ngOnInit function.

Component doesn't keep up to end itself initialization, when you already call close method. Of course in this case, such error is called.

Please remove this calling in ngOninit, and write correct logic, I mean, write calling close method in separated method, which you'll call there, where it would be needed.

Thank you.

Florella answered 21/9, 2018 at 5:38 Comment(0)
B
2

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

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

Bureaucracy answered 18/5, 2020 at 16:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.