Skip to content

Commit 085827f

Browse files
crisbetokara
authored andcommitted
fix(drawer): unable to toggle while drawer is animating (#6810)
Fixes #6376.
1 parent 766faa1 commit 085827f

File tree

2 files changed

+32
-35
lines changed

2 files changed

+32
-35
lines changed

src/lib/sidenav/drawer.spec.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ describe('MatDrawer', () => {
4646
tick();
4747
fixture.detectChanges();
4848

49-
expect(drawer.componentInstance._isAnimating).toBe(false);
5049
expect(testComponent.openCount).toBe(1);
5150
expect(testComponent.closeCount).toBe(0);
5251
expect(getComputedStyle(drawer.nativeElement).visibility).toBe('visible');
@@ -67,6 +66,27 @@ describe('MatDrawer', () => {
6766
expect(getComputedStyle(drawerBackdropElement.nativeElement).visibility).toBe('hidden');
6867
}));
6968

69+
it('should be able to close while the open animation is running', fakeAsync(() => {
70+
const fixture = TestBed.createComponent(BasicTestApp);
71+
fixture.detectChanges();
72+
73+
const testComponent: BasicTestApp = fixture.debugElement.componentInstance;
74+
fixture.debugElement.query(By.css('.open')).nativeElement.click();
75+
fixture.detectChanges();
76+
77+
expect(testComponent.openCount).toBe(0);
78+
expect(testComponent.closeCount).toBe(0);
79+
80+
fixture.debugElement.query(By.css('.close')).nativeElement.click();
81+
fixture.detectChanges();
82+
83+
tick();
84+
fixture.detectChanges();
85+
86+
expect(testComponent.openCount).toBe(1);
87+
expect(testComponent.closeCount).toBe(1);
88+
}));
89+
7090
it('does not throw when created without a drawer', fakeAsync(() => {
7191
expect(() => {
7292
let fixture = TestBed.createComponent(BasicTestApp);

src/lib/sidenav/drawer.ts

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -174,19 +174,9 @@ export class MatDrawer implements AfterContentInit, OnDestroy {
174174
/** Emits whenever the drawer has started animating. */
175175
_animationStarted = new EventEmitter<AnimationEvent>();
176176

177-
/** Whether the drawer is animating. Used to prevent overlapping animations. */
178-
_isAnimating = false;
179-
180177
/** Current state of the sidenav animation. */
181178
_animationState: 'open-instant' | 'open' | 'void' = 'void';
182179

183-
/**
184-
* Promise that resolves when the open/close animation completes. It is here for backwards
185-
* compatibility and should be removed next time we do drawer breaking changes.
186-
* @deprecated
187-
*/
188-
private _currentTogglePromise: Promise<MatDrawerToggleResult> | null;
189-
190180
/** Event emitted when the drawer is fully opened. */
191181
@Output('open') onOpen = new EventEmitter<MatDrawerToggleResult | void>();
192182

@@ -281,27 +271,23 @@ export class MatDrawer implements AfterContentInit, OnDestroy {
281271
* @param isOpen Whether the drawer should be open.
282272
*/
283273
toggle(isOpen: boolean = !this.opened): Promise<MatDrawerToggleResult> {
284-
if (!this._isAnimating) {
285-
this._opened = isOpen;
274+
this._opened = isOpen;
286275

287-
if (isOpen) {
288-
this._animationState = this._enableAnimations ? 'open' : 'open-instant';
289-
} else {
290-
this._animationState = 'void';
291-
}
292-
293-
this._currentTogglePromise = new Promise(resolve => {
294-
first.call(isOpen ? this.onOpen : this.onClose).subscribe(resolve);
295-
});
276+
if (isOpen) {
277+
this._animationState = this._enableAnimations ? 'open' : 'open-instant';
278+
} else {
279+
this._animationState = 'void';
280+
}
296281

297-
if (this._focusTrap) {
298-
this._focusTrap.enabled = this._isFocusTrapEnabled;
299-
}
282+
if (this._focusTrap) {
283+
this._focusTrap.enabled = this._isFocusTrapEnabled;
300284
}
301285

302286
// TODO(crisbeto): This promise is here for backwards-compatibility.
303287
// It should be removed next time we do breaking changes in the drawer.
304-
return this._currentTogglePromise!;
288+
return new Promise(resolve => {
289+
first.call(isOpen ? this.onOpen : this.onClose).subscribe(resolve);
290+
});
305291
}
306292

307293
/**
@@ -316,7 +302,6 @@ export class MatDrawer implements AfterContentInit, OnDestroy {
316302
}
317303

318304
_onAnimationStart(event: AnimationEvent) {
319-
this._isAnimating = true;
320305
this._animationStarted.emit(event);
321306
}
322307

@@ -328,14 +313,6 @@ export class MatDrawer implements AfterContentInit, OnDestroy {
328313
} else if (toState === 'void' && fromState.indexOf('open') === 0) {
329314
this.onClose.emit(new MatDrawerToggleResult('close', true));
330315
}
331-
332-
// Note: as of Angular 4.3, the animations module seems to fire the `start` callback before
333-
// the end if animations are disabled. Make this call async to ensure that it still fires
334-
// at the appropriate time.
335-
Promise.resolve().then(() => {
336-
this._isAnimating = false;
337-
this._currentTogglePromise = null;
338-
});
339316
}
340317

341318
get _width() {

0 commit comments

Comments
 (0)