Skip to content

Commit 9b8968c

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 3c6f7a2 commit 9b8968c

File tree

3 files changed

+33
-17
lines changed

3 files changed

+33
-17
lines changed

src/lib/sidenav/drawer.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ describe('MatDrawerContainer', () => {
326326
declarations: [
327327
DrawerContainerTwoDrawerTestApp,
328328
DrawerDelayed,
329+
DrawerSetToOpenedTrue,
329330
DrawerContainerStateChangesTestApp,
330331
],
331332
});
@@ -417,6 +418,17 @@ describe('MatDrawerContainer', () => {
417418
expect(parseInt(contentElement.style.marginLeft)).toBeLessThan(initialMargin);
418419
}));
419420

421+
it('should not animate when the sidenav is open on load ', fakeAsync(() => {
422+
const fixture = TestBed.createComponent(DrawerSetToOpenedTrue);
423+
424+
fixture.detectChanges();
425+
tick();
426+
427+
const container = fixture.debugElement.nativeElement.querySelector('.mat-drawer-container');
428+
429+
expect(container.classList).not.toContain('mat-drawer-transition');
430+
}));
431+
420432
});
421433

422434

src/lib/sidenav/drawer.ts

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,8 @@ 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';
37+
import {RxChain, filter, first, startWith, takeUntil} from '@angular/cdk/rxjs';
4038

4139

4240
/** Throws an exception when two MatDrawer are matching the same position. */
@@ -117,7 +115,7 @@ export class MatDrawerContent implements AfterContentInit {
117115
host: {
118116
'class': 'mat-drawer',
119117
'[@transform]': '_animationState',
120-
'(@transform.start)': '_onAnimationStart()',
118+
'(@transform.start)': '_onAnimationStart($event)',
121119
'(@transform.done)': '_onAnimationEnd($event)',
122120
'(keydown)': 'handleKeydown($event)',
123121
// must prevent the browser from aligning text based on value
@@ -177,7 +175,7 @@ export class MatDrawer implements AfterContentInit, OnDestroy {
177175
private _opened: boolean = false;
178176

179177
/** Emits whenever the drawer has started animating. */
180-
_animationStarted = new EventEmitter<void>();
178+
_animationStarted = new EventEmitter<AnimationEvent>();
181179

182180
/** Whether the drawer is animating. Used to prevent overlapping animations. */
183181
_isAnimating = false;
@@ -320,9 +318,9 @@ export class MatDrawer implements AfterContentInit, OnDestroy {
320318
}
321319
}
322320

323-
_onAnimationStart() {
321+
_onAnimationStart(event: AnimationEvent) {
324322
this._isAnimating = true;
325-
this._animationStarted.emit();
323+
this._animationStarted.emit(event);
326324
}
327325

328326
_onAnimationEnd(event: AnimationEvent) {
@@ -453,13 +451,19 @@ export class MatDrawerContainer implements AfterContentInit, OnDestroy {
453451
* is properly hidden.
454452
*/
455453
private _watchDrawerToggle(drawer: MatDrawer): void {
456-
takeUntil.call(drawer._animationStarted, this._drawers.changes).subscribe(() => {
457-
// Set the transition class on the container so that the animations occur. This should not
458-
// be set initially because animations should only be triggered via a change in state.
459-
this._renderer.addClass(this._element.nativeElement, 'mat-drawer-transition');
460-
this._updateContentMargins();
461-
this._changeDetectorRef.markForCheck();
462-
});
454+
RxChain.from(drawer._animationStarted)
455+
.call(takeUntil, this._drawers.changes)
456+
.call(filter, (event: AnimationEvent) => event.fromState !== event.toState)
457+
.subscribe((event: AnimationEvent) => {
458+
// Set the transition class on the container so that the animations occur. This should not
459+
// be set initially because animations should only be triggered via a change in state.
460+
if (event.toState !== 'open-instant') {
461+
this._renderer.addClass(this._element.nativeElement, 'mat-drawer-transition');
462+
}
463+
464+
this._updateContentMargins();
465+
this._changeDetectorRef.markForCheck();
466+
});
463467

464468
if (drawer.mode !== 'side') {
465469
takeUntil.call(merge(drawer.onOpen, drawer.onClose), this._drawers.changes).subscribe(() =>
@@ -468,8 +472,8 @@ export class MatDrawerContainer implements AfterContentInit, OnDestroy {
468472
}
469473

470474
/**
471-
* Subscribes to drawer onPositionChanged event in order to re-validate drawers when the position
472-
* changes.
475+
* Subscribes to drawer onPositionChanged event in order to
476+
* re-validate drawers when the position changes.
473477
*/
474478
private _watchDrawerPosition(drawer: MatDrawer): void {
475479
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 MatSidenavContent extends MatDrawerContent {
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)