Skip to content

Commit a099082

Browse files
committed
fix(drawer): unable to toggle while drawer is animating
Fixes not being able to toggle a drawer while it is mid-animation. Fixes angular#6376.
1 parent 53c42a4 commit a099082

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
@@ -45,7 +45,6 @@ describe('MatDrawer', () => {
4545
tick();
4646
fixture.detectChanges();
4747

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

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

src/lib/sidenav/drawer.ts

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

183-
/** Whether the drawer is animating. Used to prevent overlapping animations. */
184-
_isAnimating = false;
185-
186183
/** Current state of the sidenav animation. */
187184
_animationState: 'open-instant' | 'open' | 'void' = 'void';
188185

189-
/**
190-
* Promise that resolves when the open/close animation completes. It is here for backwards
191-
* compatibility and should be removed next time we do drawer breaking changes.
192-
* @deprecated
193-
*/
194-
private _currentTogglePromise: Promise<MatDrawerToggleResult> | null;
195-
196186
/** Event emitted when the drawer is fully opened. */
197187
@Output('open') onOpen = new EventEmitter<MatDrawerToggleResult | void>();
198188

@@ -287,27 +277,23 @@ export class MatDrawer implements AfterContentInit, OnDestroy {
287277
* @param isOpen Whether the drawer should be open.
288278
*/
289279
toggle(isOpen: boolean = !this.opened): Promise<MatDrawerToggleResult> {
290-
if (!this._isAnimating) {
291-
this._opened = isOpen;
280+
this._opened = isOpen;
292281

293-
if (isOpen) {
294-
this._animationState = this._enableAnimations ? 'open' : 'open-instant';
295-
} else {
296-
this._animationState = 'void';
297-
}
298-
299-
this._currentTogglePromise = new Promise(resolve => {
300-
first.call(isOpen ? this.onOpen : this.onClose).subscribe(resolve);
301-
});
282+
if (isOpen) {
283+
this._animationState = this._enableAnimations ? 'open' : 'open-instant';
284+
} else {
285+
this._animationState = 'void';
286+
}
302287

303-
if (this._focusTrap) {
304-
this._focusTrap.enabled = this.isFocusTrapEnabled;
305-
}
288+
if (this._focusTrap) {
289+
this._focusTrap.enabled = this.isFocusTrapEnabled;
306290
}
307291

308292
// TODO(crisbeto): This promise is here for backwards-compatibility.
309293
// It should be removed next time we do breaking changes in the drawer.
310-
return this._currentTogglePromise!;
294+
return new Promise(resolve => {
295+
first.call(isOpen ? this.onOpen : this.onClose).subscribe(resolve);
296+
});
311297
}
312298

313299
/**
@@ -322,7 +308,6 @@ export class MatDrawer implements AfterContentInit, OnDestroy {
322308
}
323309

324310
_onAnimationStart() {
325-
this._isAnimating = true;
326311
this._animationStarted.emit();
327312
}
328313

@@ -334,14 +319,6 @@ export class MatDrawer implements AfterContentInit, OnDestroy {
334319
} else if (toState === 'void' && fromState === 'open') {
335320
this.onClose.emit(new MatDrawerToggleResult('close', true));
336321
}
337-
338-
// Note: as of Angular 4.3, the animations module seems to fire the `start` callback before
339-
// the end if animations are disabled. Make this call async to ensure that it still fires
340-
// at the appropriate time.
341-
Promise.resolve().then(() => {
342-
this._isAnimating = false;
343-
this._currentTogglePromise = null;
344-
});
345322
}
346323

347324
get _width() {

0 commit comments

Comments
 (0)