Skip to content

Commit

Permalink
fix(drawer): drawer container not reacting to drawer removal and mode…
Browse files Browse the repository at this point in the history
… change

* Fixes the drawer container not reacting if one of the drawers is destroyed.
* Fixes the drawer container not reacting if the mode of a drawer is changed.

Fixes #6271.
  • Loading branch information
crisbeto committed Sep 26, 2017
1 parent 3571f68 commit db61f29
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 9 deletions.
63 changes: 62 additions & 1 deletion src/lib/sidenav/drawer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,11 @@ describe('MdDrawerContainer', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MdSidenavModule, A11yModule, PlatformModule, NoopAnimationsModule],
declarations: [DrawerContainerTwoDrawerTestApp, DrawerDelayed],
declarations: [
DrawerContainerTwoDrawerTestApp,
DrawerDelayed,
DrawerContainerStateChangesTestApp,
],
});

TestBed.compileComponents();
Expand Down Expand Up @@ -363,6 +367,47 @@ describe('MdDrawerContainer', () => {

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

it('should recalculate the margin if a drawer is destroyed', fakeAsync(() => {
const fixture = TestBed.createComponent(DrawerContainerStateChangesTestApp);

fixture.detectChanges();
fixture.componentInstance.drawer.open();
fixture.detectChanges();
tick();
fixture.detectChanges();

const contentElement = fixture.debugElement.nativeElement.querySelector('.mat-drawer-content');
const initialMargin = parseInt(contentElement.style.marginLeft);

expect(initialMargin).toBeGreaterThan(0);

fixture.componentInstance.renderDrawer = false;
fixture.detectChanges();

expect(parseInt(contentElement.style.marginLeft)).toBeLessThan(initialMargin);
}));

it('should recalculate the margin if the drawer mode is changed', fakeAsync(() => {
const fixture = TestBed.createComponent(DrawerContainerStateChangesTestApp);

fixture.detectChanges();
fixture.componentInstance.drawer.open();
fixture.detectChanges();
tick();
fixture.detectChanges();

const contentElement = fixture.debugElement.nativeElement.querySelector('.mat-drawer-content');
const initialMargin = parseInt(contentElement.style.marginLeft);

expect(initialMargin).toBeGreaterThan(0);

fixture.componentInstance.mode = 'over';
fixture.detectChanges();

expect(parseInt(contentElement.style.marginLeft)).toBeLessThan(initialMargin);
}));

});


Expand Down Expand Up @@ -474,3 +519,19 @@ class DrawerDelayed {
@ViewChild(MdDrawer) drawer: MdDrawer;
showDrawer = false;
}


@Component({
template: `
<md-drawer-container>
<md-drawer *ngIf="renderDrawer" [mode]="mode"></md-drawer>
</md-drawer-container>`,
})
class DrawerContainerStateChangesTestApp {
@ViewChild(MdDrawer) drawer: MdDrawer;
@ViewChild(MdDrawerContainer) drawerContainer: MdDrawerContainer;

mode = 'side';
renderDrawer = true;
}

28 changes: 20 additions & 8 deletions src/lib/sidenav/drawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,8 @@ export class MdDrawerContainer implements AfterContentInit, OnDestroy {
private _left: MdDrawer | null;
private _right: MdDrawer | null;

/** Subscription to the Directionality change EventEmitter. */
private _dirChangeSubscription = Subscription.EMPTY;
/** Emits when the component is destroyed. */
private _destroyed = new Subject<void>();

_contentMargins = new Subject<{left: number, right: number}>();

Expand All @@ -409,23 +409,34 @@ export class MdDrawerContainer implements AfterContentInit, OnDestroy {
// If a `Dir` directive exists up the tree, listen direction changes and update the left/right
// properties to point to the proper start/end.
if (_dir != null) {
this._dirChangeSubscription = _dir.change.subscribe(() => this._validateDrawers());
takeUntil.call(_dir.change, this._destroyed).subscribe(() => this._validateDrawers());
}
}

ngAfterContentInit() {
startWith.call(this._drawers.changes, null).subscribe(() => {
this._validateDrawers();

this._drawers.forEach((drawer: MdDrawer) => {
this._watchDrawerToggle(drawer);
this._watchDrawerPosition(drawer);
this._watchDrawerMode(drawer);
});

if (!this._drawers.length ||
this._isDrawerOpen(this._start) ||
this._isDrawerOpen(this._end)
) {
this._updateContentMargins();
}

this._changeDetectorRef.markForCheck();
});
}

ngOnDestroy() {
this._dirChangeSubscription.unsubscribe();
this._destroyed.next();
this._destroyed.complete();
}

/** Calls `open` of both start and end drawers */
Expand Down Expand Up @@ -478,10 +489,11 @@ export class MdDrawerContainer implements AfterContentInit, OnDestroy {
/** Subscribes to changes in drawer mode so we can run change detection. */
private _watchDrawerMode(drawer: MdDrawer): void {
if (drawer) {
takeUntil.call(drawer._modeChanged, this._drawers.changes).subscribe(() => {
this._updateContentMargins();
this._changeDetectorRef.markForCheck();
});
takeUntil.call(drawer._modeChanged, merge(this._drawers.changes, this._destroyed))
.subscribe(() => {
this._updateContentMargins();
this._changeDetectorRef.markForCheck();
});
}
}

Expand Down

0 comments on commit db61f29

Please sign in to comment.