Skip to content

Commit 8e77261

Browse files
crisbetoandrewseguin
authored andcommitted
fix(snack-bar): subsequent snack bars not opening; animation issues (#7086)
* Fixes subsequent snack bars not showing up if they are opened while another snack bar is open. This was due to the latter snack bar getting closed immediately, because one of the animation events coming in is `void->void`. * Simplifies the logic for determining the animation state. Using the getter ended up passing returning an invalid state in some cases (e.g. `undefined-top` or `undefined-bottom`). Fixes #7063.
1 parent 6bd6b9f commit 8e77261

File tree

2 files changed

+15
-23
lines changed

2 files changed

+15
-23
lines changed

src/lib/snack-bar/snack-bar-container.ts

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ import {Subject} from 'rxjs/Subject';
3838
import {MatSnackBarConfig} from './snack-bar-config';
3939

4040

41-
export type SnackBarState = 'visible' | 'hidden' | 'void';
42-
4341
// TODO(jelbourn): we can't use constants from animation.ts here because you can't use
4442
// a text interpolation in anything that is analyzed statically with ngc (for AoT compile).
4543
export const SHOW_ANIMATION = '225ms cubic-bezier(0.4,0.0,1,1)';
@@ -60,7 +58,7 @@ export const HIDE_ANIMATION = '195ms cubic-bezier(0.0,0.0,0.2,1)';
6058
host: {
6159
'role': 'alert',
6260
'class': 'mat-snack-bar-container',
63-
'[@state]': 'getAnimationState()',
61+
'[@state]': '_animationState',
6462
'(@state.done)': 'onAnimationEnd($event)'
6563
},
6664
animations: [
@@ -93,7 +91,7 @@ export class MatSnackBarContainer extends BasePortalHost implements OnDestroy {
9391
_onEnter: Subject<any> = new Subject();
9492

9593
/** The state of the snack bar animations. */
96-
private _animationState: SnackBarState;
94+
_animationState = 'void';
9795

9896
/** The snack bar configuration. */
9997
snackBarConfig: MatSnackBarConfig;
@@ -106,14 +104,6 @@ export class MatSnackBarContainer extends BasePortalHost implements OnDestroy {
106104
super();
107105
}
108106

109-
/**
110-
* Gets the current animation state both combining one of the possibilities from
111-
* SnackBarState and the vertical location.
112-
*/
113-
getAnimationState(): string {
114-
return `${this._animationState}-${this.snackBarConfig.verticalPosition}`;
115-
}
116-
117107
/** Attach a component portal as content to this snack bar container. */
118108
attachComponentPortal<T>(portal: ComponentPortal<T>): ComponentRef<T> {
119109
if (this._portalHost.hasAttached()) {
@@ -146,11 +136,13 @@ export class MatSnackBarContainer extends BasePortalHost implements OnDestroy {
146136

147137
/** Handle end of animations, updating the state of the snackbar. */
148138
onAnimationEnd(event: AnimationEvent) {
149-
if (event.toState === 'void' || event.toState.startsWith('hidden')) {
139+
const {fromState, toState} = event;
140+
141+
if ((toState === 'void' && fromState !== 'void') || toState.startsWith('hidden')) {
150142
this._completeExit();
151143
}
152144

153-
if (event.toState.startsWith('visible')) {
145+
if (toState.startsWith('visible')) {
154146
// Note: we shouldn't use `this` inside the zone callback,
155147
// because it can cause a memory leak.
156148
const onEnter = this._onEnter;
@@ -165,14 +157,14 @@ export class MatSnackBarContainer extends BasePortalHost implements OnDestroy {
165157
/** Begin animation of snack bar entrance into view. */
166158
enter(): void {
167159
if (!this._destroyed) {
168-
this._animationState = 'visible';
160+
this._animationState = `visible-${this.snackBarConfig.verticalPosition}`;
169161
this._changeDetectorRef.detectChanges();
170162
}
171163
}
172164

173165
/** Begin animation of the snack bar exiting from view. */
174166
exit(): Observable<void> {
175-
this._animationState = 'hidden';
167+
this._animationState = `hidden-${this.snackBarConfig.verticalPosition}`;
176168
return this._onExit;
177169
}
178170

src/lib/snack-bar/snack-bar.spec.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,12 @@ describe('MatSnackBar', () => {
186186
let snackBarRef = snackBar.open(simpleMessage, undefined, config);
187187

188188
viewContainerFixture.detectChanges();
189-
expect(snackBarRef.containerInstance.getAnimationState())
189+
expect(snackBarRef.containerInstance._animationState)
190190
.toBe('visible-bottom', `Expected the animation state would be 'visible-bottom'.`);
191191
snackBarRef.dismiss();
192192

193193
viewContainerFixture.detectChanges();
194-
expect(snackBarRef.containerInstance.getAnimationState())
194+
expect(snackBarRef.containerInstance._animationState)
195195
.toBe('hidden-bottom', `Expected the animation state would be 'hidden-bottom'.`);
196196
});
197197

@@ -201,7 +201,7 @@ describe('MatSnackBar', () => {
201201
snackBarRef.dismiss();
202202

203203
viewContainerFixture.detectChanges();
204-
expect(snackBarRef.containerInstance.getAnimationState())
204+
expect(snackBarRef.containerInstance._animationState)
205205
.toBe('hidden-bottom', `Expected the animation state would be 'hidden-bottom'.`);
206206
});
207207

@@ -212,7 +212,7 @@ describe('MatSnackBar', () => {
212212
let dismissObservableCompleted = false;
213213

214214
viewContainerFixture.detectChanges();
215-
expect(snackBarRef.containerInstance.getAnimationState())
215+
expect(snackBarRef.containerInstance._animationState)
216216
.toBe('visible-bottom', `Expected the animation state would be 'visible-bottom'.`);
217217

218218
let config2 = {viewContainerRef: testViewContainerRef};
@@ -225,9 +225,9 @@ describe('MatSnackBar', () => {
225225

226226
viewContainerFixture.whenStable().then(() => {
227227
expect(dismissObservableCompleted).toBe(true);
228-
expect(snackBarRef.containerInstance.getAnimationState())
228+
expect(snackBarRef.containerInstance._animationState)
229229
.toBe('hidden-bottom', `Expected the animation state would be 'hidden-bottom'.`);
230-
expect(snackBarRef2.containerInstance.getAnimationState())
230+
expect(snackBarRef2.containerInstance._animationState)
231231
.toBe('visible-bottom', `Expected the animation state would be 'visible-bottom'.`);
232232
});
233233
}));
@@ -248,7 +248,7 @@ describe('MatSnackBar', () => {
248248

249249
// Wait for the snackbar open animation to finish.
250250
viewContainerFixture.whenStable().then(() => {
251-
expect(snackBarRef.containerInstance.getAnimationState())
251+
expect(snackBarRef.containerInstance._animationState)
252252
.toBe('visible-bottom', `Expected the animation state would be 'visible-bottom'.`);
253253
});
254254
});

0 commit comments

Comments
 (0)