Components: Snackbar.open inside ngOnInit produces an ExpressionChangedAfterItHasBeenCheckedError error

Created on 16 May 2018  ·  9Comments  ·  Source: angular/components

Bug, feature request, or proposal:

Bug

What is the expected behavior?

Calling snackbarService.open() should not produce errors, even if the DI has just instantiated the snackbar service.

What is the current behavior?

When calling snackbarService.open() inside ngOnInit, an error is thrown:

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '@state: undefined'. Current value: '@state: visible-bottom'. 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 ?

What are the steps to reproduce?

Just add a call to snackbar service's open, inside ngOnInit
https://stackblitz.com/edit/angular-3ma9xb

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Angular 6.0.2, material 6.0.0-rc14

Is there anything else we should know?

I'm guessing that when you inject the service at the constructor, the snackbar div gets appended to the DOM, and if open() gets called too quickly, the change detection is still in progress for the div's attributes.

Most helpful comment

That’s an even dirtier hack 🤓...

All 9 comments

@splitt3r Yes, that's how I worked around it (small setTimeout). But I guess it feels hacky. 🤷‍♂️

Ah ok. But then you should upvote the other issue and not create a new one 😀.

Closing the issue since this is a limitation in core that we can't do much about in Material.

@crisbeto I'm afraid I don't agree with you. There's ChangeDetectorRef for example. @splitt3r the "small setTimeout" it's just a workaround... feels too hacky. I don't think this is a core limitation, it should work regardless of the change detection strategy used in our side.

For anyone that don't want to use the setTimeout hack you can do it like this:

Promise.resolve().then(() => { this.snackBar.open('Message archived', null, { duration: 2000 }); });

That’s an even dirtier hack 🤓...

Closing the issue since this is a limitation in core that we can't do much about in Material.

so does that snackbar works only on button click?

settimeout is shity fix as well as promise resolve

what angular core limitation are you talking about?
change detection should be called somewhere in snackbar code
is it possible to reopen this issue?

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings