Skip to content

Commit fc16ed9

Browse files
committed
fix(drawer): drawer container animating when open by default
* Prevents the drawer container from animating if it's open on load. * Fixes `_updateStyles` being called twice in a row on init, because the first animations are `void->void` and `void->open-instant`. Fixes #7007.
1 parent 3571f68 commit fc16ed9

File tree

3 files changed

+34
-18
lines changed

3 files changed

+34
-18
lines changed

src/lib/sidenav/drawer.spec.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ describe('MdDrawerContainer', () => {
314314
beforeEach(async(() => {
315315
TestBed.configureTestingModule({
316316
imports: [MdSidenavModule, A11yModule, PlatformModule, NoopAnimationsModule],
317-
declarations: [DrawerContainerTwoDrawerTestApp, DrawerDelayed],
317+
declarations: [DrawerContainerTwoDrawerTestApp, DrawerDelayed, DrawerSetToOpenedTrue],
318318
});
319319

320320
TestBed.compileComponents();
@@ -363,6 +363,18 @@ describe('MdDrawerContainer', () => {
363363

364364
expect(parseInt(contentElement.style.marginLeft)).toBeGreaterThan(0);
365365
}));
366+
367+
it('should not animate when the sidenav is open on load ', fakeAsync(() => {
368+
const fixture = TestBed.createComponent(DrawerSetToOpenedTrue);
369+
370+
fixture.detectChanges();
371+
tick();
372+
373+
const container = fixture.debugElement.nativeElement.querySelector('.mat-drawer-container');
374+
375+
expect(container.classList).not.toContain('mat-drawer-transition');
376+
}));
377+
366378
});
367379

368380

src/lib/sidenav/drawer.ts

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,9 @@ import {
3333
} from '@angular/core';
3434
import {DOCUMENT} from '@angular/platform-browser';
3535
import {merge} from 'rxjs/observable/merge';
36-
import {first} from 'rxjs/operator/first';
37-
import {startWith} from 'rxjs/operator/startWith';
38-
import {takeUntil} from 'rxjs/operator/takeUntil';
3936
import {Subject} from 'rxjs/Subject';
4037
import {Subscription} from 'rxjs/Subscription';
38+
import {RxChain, filter, first, startWith, takeUntil} from '@angular/cdk/rxjs';
4139

4240

4341
/** Throws an exception when two MdDrawer are matching the same position. */
@@ -118,7 +116,7 @@ export class MdDrawerContent implements AfterContentInit {
118116
host: {
119117
'class': 'mat-drawer',
120118
'[@transform]': '_animationState',
121-
'(@transform.start)': '_onAnimationStart()',
119+
'(@transform.start)': '_onAnimationStart($event)',
122120
'(@transform.done)': '_onAnimationEnd($event)',
123121
'(keydown)': 'handleKeydown($event)',
124122
// must prevent the browser from aligning text based on value
@@ -178,7 +176,7 @@ export class MdDrawer implements AfterContentInit, OnDestroy {
178176
private _opened: boolean = false;
179177

180178
/** Emits whenever the drawer has started animating. */
181-
_animationStarted = new EventEmitter<void>();
179+
_animationStarted = new EventEmitter<AnimationEvent>();
182180

183181
/** Whether the drawer is animating. Used to prevent overlapping animations. */
184182
_isAnimating = false;
@@ -321,9 +319,9 @@ export class MdDrawer implements AfterContentInit, OnDestroy {
321319
}
322320
}
323321

324-
_onAnimationStart() {
322+
_onAnimationStart(event: AnimationEvent) {
325323
this._isAnimating = true;
326-
this._animationStarted.emit();
324+
this._animationStarted.emit(event);
327325
}
328326

329327
_onAnimationEnd(event: AnimationEvent) {
@@ -444,13 +442,19 @@ export class MdDrawerContainer implements AfterContentInit, OnDestroy {
444442
* is properly hidden.
445443
*/
446444
private _watchDrawerToggle(drawer: MdDrawer): void {
447-
takeUntil.call(drawer._animationStarted, this._drawers.changes).subscribe(() => {
448-
// Set the transition class on the container so that the animations occur. This should not
449-
// be set initially because animations should only be triggered via a change in state.
450-
this._renderer.addClass(this._element.nativeElement, 'mat-drawer-transition');
451-
this._updateContentMargins();
452-
this._changeDetectorRef.markForCheck();
453-
});
445+
RxChain.from(drawer._animationStarted)
446+
.call(takeUntil, this._drawers.changes)
447+
.call(filter, (event: AnimationEvent) => event.fromState !== event.toState)
448+
.subscribe((event: AnimationEvent) => {
449+
// Set the transition class on the container so that the animations occur. This should not
450+
// be set initially because animations should only be triggered via a change in state.
451+
if (event.toState !== 'open-instant') {
452+
this._renderer.addClass(this._element.nativeElement, 'mat-drawer-transition');
453+
}
454+
455+
this._updateContentMargins();
456+
this._changeDetectorRef.markForCheck();
457+
});
454458

455459
if (drawer.mode !== 'side') {
456460
takeUntil.call(merge(drawer.onOpen, drawer.onClose), this._drawers.changes).subscribe(() =>
@@ -459,8 +463,8 @@ export class MdDrawerContainer implements AfterContentInit, OnDestroy {
459463
}
460464

461465
/**
462-
* Subscribes to drawer onPositionChanged event in order to re-validate drawers when the position
463-
* changes.
466+
* Subscribes to drawer onPositionChanged event in order to
467+
* re-validate drawers when the position changes.
464468
*/
465469
private _watchDrawerPosition(drawer: MdDrawer): void {
466470
if (!drawer) {

src/lib/sidenav/sidenav.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export class MdSidenavContent extends MdDrawerContent {
6161
'class': 'mat-drawer mat-sidenav',
6262
'tabIndex': '-1',
6363
'[@transform]': '_animationState',
64-
'(@transform.start)': '_onAnimationStart()',
64+
'(@transform.start)': '_onAnimationStart($event)',
6565
'(@transform.done)': '_onAnimationEnd($event)',
6666
'(keydown)': 'handleKeydown($event)',
6767
// must prevent the browser from aligning text based on value

0 commit comments

Comments
 (0)