Skip to content

Commit b0b91f4

Browse files
crisbetoandrewseguin
authored andcommitted
fix(drawer): drawer container not reacting to drawer removal (#7060)
Fixes the drawer container not reacting if one of the drawers is destroyed. Fixes #6271.
1 parent c82fca8 commit b0b91f4

File tree

2 files changed

+81
-9
lines changed

2 files changed

+81
-9
lines changed

src/lib/sidenav/drawer.spec.ts

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,11 @@ describe('MatDrawerContainer', () => {
323323
beforeEach(async(() => {
324324
TestBed.configureTestingModule({
325325
imports: [MatSidenavModule, A11yModule, PlatformModule, NoopAnimationsModule],
326-
declarations: [DrawerContainerTwoDrawerTestApp, DrawerDelayed],
326+
declarations: [
327+
DrawerContainerTwoDrawerTestApp,
328+
DrawerDelayed,
329+
DrawerContainerStateChangesTestApp,
330+
],
327331
});
328332

329333
TestBed.compileComponents();
@@ -372,6 +376,47 @@ describe('MatDrawerContainer', () => {
372376

373377
expect(parseInt(contentElement.style.marginLeft)).toBeGreaterThan(0);
374378
}));
379+
380+
it('should recalculate the margin if a drawer is destroyed', fakeAsync(() => {
381+
const fixture = TestBed.createComponent(DrawerContainerStateChangesTestApp);
382+
383+
fixture.detectChanges();
384+
fixture.componentInstance.drawer.open();
385+
fixture.detectChanges();
386+
tick();
387+
fixture.detectChanges();
388+
389+
const contentElement = fixture.debugElement.nativeElement.querySelector('.mat-drawer-content');
390+
const initialMargin = parseInt(contentElement.style.marginLeft);
391+
392+
expect(initialMargin).toBeGreaterThan(0);
393+
394+
fixture.componentInstance.renderDrawer = false;
395+
fixture.detectChanges();
396+
397+
expect(parseInt(contentElement.style.marginLeft)).toBeLessThan(initialMargin);
398+
}));
399+
400+
it('should recalculate the margin if the drawer mode is changed', fakeAsync(() => {
401+
const fixture = TestBed.createComponent(DrawerContainerStateChangesTestApp);
402+
403+
fixture.detectChanges();
404+
fixture.componentInstance.drawer.open();
405+
fixture.detectChanges();
406+
tick();
407+
fixture.detectChanges();
408+
409+
const contentElement = fixture.debugElement.nativeElement.querySelector('.mat-drawer-content');
410+
const initialMargin = parseInt(contentElement.style.marginLeft);
411+
412+
expect(initialMargin).toBeGreaterThan(0);
413+
414+
fixture.componentInstance.mode = 'over';
415+
fixture.detectChanges();
416+
417+
expect(parseInt(contentElement.style.marginLeft)).toBeLessThan(initialMargin);
418+
}));
419+
375420
});
376421

377422

@@ -485,3 +530,19 @@ class DrawerDelayed {
485530
@ViewChild(MatDrawer) drawer: MatDrawer;
486531
showDrawer = false;
487532
}
533+
534+
535+
@Component({
536+
template: `
537+
<mat-drawer-container>
538+
<mat-drawer *ngIf="renderDrawer" [mode]="mode"></mat-drawer>
539+
</mat-drawer-container>`,
540+
})
541+
class DrawerContainerStateChangesTestApp {
542+
@ViewChild(MatDrawer) drawer: MatDrawer;
543+
@ViewChild(MatDrawerContainer) drawerContainer: MatDrawerContainer;
544+
545+
mode = 'side';
546+
renderDrawer = true;
547+
}
548+

src/lib/sidenav/drawer.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,8 @@ export class MatDrawerContainer implements AfterContentInit, OnDestroy {
398398
private _left: MatDrawer | null;
399399
private _right: MatDrawer | null;
400400

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

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

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

416416
ngAfterContentInit() {
417417
startWith.call(this._drawers.changes, null).subscribe(() => {
418418
this._validateDrawers();
419+
419420
this._drawers.forEach((drawer: MatDrawer) => {
420421
this._watchDrawerToggle(drawer);
421422
this._watchDrawerPosition(drawer);
422423
this._watchDrawerMode(drawer);
423424
});
425+
426+
if (!this._drawers.length ||
427+
this._isDrawerOpen(this._start) ||
428+
this._isDrawerOpen(this._end)) {
429+
this._updateContentMargins();
430+
}
431+
432+
this._changeDetectorRef.markForCheck();
424433
});
425434
}
426435

427436
ngOnDestroy() {
428-
this._dirChangeSubscription.unsubscribe();
437+
this._destroyed.next();
438+
this._destroyed.complete();
429439
}
430440

431441
/** Calls `open` of both start and end drawers */
@@ -478,10 +488,11 @@ export class MatDrawerContainer implements AfterContentInit, OnDestroy {
478488
/** Subscribes to changes in drawer mode so we can run change detection. */
479489
private _watchDrawerMode(drawer: MatDrawer): void {
480490
if (drawer) {
481-
takeUntil.call(drawer._modeChanged, this._drawers.changes).subscribe(() => {
482-
this._updateContentMargins();
483-
this._changeDetectorRef.markForCheck();
484-
});
491+
takeUntil.call(drawer._modeChanged, merge(this._drawers.changes, this._destroyed))
492+
.subscribe(() => {
493+
this._updateContentMargins();
494+
this._changeDetectorRef.markForCheck();
495+
});
485496
}
486497
}
487498

0 commit comments

Comments
 (0)