Skip to content

Commit

Permalink
fix(sidenav): container not reacting to changes to sidenavs added aft…
Browse files Browse the repository at this point in the history
…er init

Fixes the sidenav container not reacting to sidenavs that were added after initialization.

Fixes angular#6127.
  • Loading branch information
crisbeto committed Jul 31, 2017
1 parent 846899d commit b9da8a5
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 21 deletions.
37 changes: 32 additions & 5 deletions src/lib/sidenav/sidenav.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,9 +459,7 @@ describe('MdSidenavContainer', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MdSidenavModule, A11yModule, PlatformModule],
declarations: [
SidenavContainerTwoSidenavTestApp
],
declarations: [SidenavContainerTwoSidenavTestApp, SidenavDelayed],
});

TestBed.compileComponents();
Expand Down Expand Up @@ -490,6 +488,23 @@ describe('MdSidenavContainer', () => {
});
}));
});

it('should animate the content when a sidenav is added at a later point', () => {
const fixture = TestBed.createComponent(SidenavDelayed);

fixture.detectChanges();

const contentElement = fixture.debugElement.nativeElement.querySelector('.mat-sidenav-content');

expect(parseInt(contentElement.style.marginLeft)).toBe(0);

fixture.componentInstance.showSidenav = true;
fixture.detectChanges();
fixture.componentInstance.sidenav.open();
fixture.detectChanges();

expect(parseInt(contentElement.style.marginLeft)).toBeGreaterThan(0);
});
});


Expand All @@ -506,8 +521,7 @@ class SidenavContainerNoSidenavTestApp { }
</md-sidenav-container>`,
})
class SidenavContainerTwoSidenavTestApp {
@ViewChild(MdSidenavContainer)
sidenavContainer: MdSidenavContainer;
@ViewChild(MdSidenavContainer) sidenavContainer: MdSidenavContainer;
}

/** Test component that contains an MdSidenavContainer and one MdSidenav. */
Expand Down Expand Up @@ -601,3 +615,16 @@ class SidenavDynamicAlign {
class SidenavWitFocusableElements {
mode: string = 'over';
}


@Component({
template: `
<md-sidenav-container>
<md-sidenav *ngIf="showSidenav" #sidenav mode="side">Sidenav</md-sidenav>
</md-sidenav-container>
`,
})
class SidenavDelayed {
@ViewChild(MdSidenav) sidenav: MdSidenav;
showSidenav = false;
}
33 changes: 17 additions & 16 deletions src/lib/sidenav/sidenav.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
import {Directionality, coerceBooleanProperty} from '../core';
import {FocusTrapFactory, FocusTrap} from '../core/a11y/focus-trap';
import {ESCAPE} from '../core/keyboard/keycodes';
import {first} from '../core/rxjs/index';
import {first, takeUntil, startWith} from '../core/rxjs/index';
import {DOCUMENT} from '@angular/platform-browser';
import {merge} from 'rxjs/observable/merge';

Expand Down Expand Up @@ -372,13 +372,13 @@ export class MdSidenavContainer implements AfterContentInit {
}

ngAfterContentInit() {
// On changes, assert on consistency.
this._sidenavs.changes.subscribe(() => this._validateDrawers());
this._sidenavs.forEach((sidenav: MdSidenav) => {
this._watchSidenavToggle(sidenav);
this._watchSidenavAlign(sidenav);
startWith.call(this._sidenavs.changes, null).subscribe(() => {
this._validateDrawers();
this._sidenavs.forEach((sidenav: MdSidenav) => {
this._watchSidenavToggle(sidenav);
this._watchSidenavAlign(sidenav);
});
});
this._validateDrawers();
}

/** Calls `open` of both start and end sidenavs */
Expand All @@ -401,16 +401,17 @@ export class MdSidenavContainer implements AfterContentInit {
* is properly hidden.
*/
private _watchSidenavToggle(sidenav: MdSidenav): void {
merge(sidenav.onOpenStart, sidenav.onCloseStart).subscribe(() => {
// Set the transition class on the container so that the animations occur. This should not
// be set initially because animations should only be triggered via a change in state.
this._renderer.addClass(this._element.nativeElement, 'mat-sidenav-transition');
this._changeDetectorRef.markForCheck();
});
takeUntil.call(merge(sidenav.onOpenStart, sidenav.onCloseStart), this._sidenavs.changes)
.subscribe(() => {
// Set the transition class on the container so that the animations occur. This should not
// be set initially because animations should only be triggered via a change in state.
this._renderer.addClass(this._element.nativeElement, 'mat-sidenav-transition');
this._changeDetectorRef.markForCheck();
});

if (sidenav.mode !== 'side') {
sidenav.onOpen.subscribe(() => this._setContainerClass(true));
sidenav.onClose.subscribe(() => this._setContainerClass(false));
takeUntil.call(merge(sidenav.onOpen, sidenav.onClose), this._sidenavs.changes).subscribe(() =>
this._setContainerClass(sidenav.opened));
}
}

Expand All @@ -424,7 +425,7 @@ export class MdSidenavContainer implements AfterContentInit {
}
// NOTE: We need to wait for the microtask queue to be empty before validating,
// since both drawers may be swapping sides at the same time.
sidenav.onAlignChanged.subscribe(() =>
takeUntil.call(sidenav.onAlignChanged, this._sidenavs.changes).subscribe(() =>
first.call(this._ngZone.onMicrotaskEmpty).subscribe(() => this._validateDrawers()));
}

Expand Down

0 comments on commit b9da8a5

Please sign in to comment.