Skip to content

Commit 8bd26dc

Browse files
committed
fix(drawer): drawer container not reacting to drawer removal
Fixes the drawer container not reacting if one of the drawers is destroyed. Fixes #6271.
1 parent 53c42a4 commit 8bd26dc

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
@@ -314,7 +314,11 @@ describe('MatDrawerContainer', () => {
314314
beforeEach(async(() => {
315315
TestBed.configureTestingModule({
316316
imports: [MatSidenavModule, A11yModule, PlatformModule, NoopAnimationsModule],
317-
declarations: [DrawerContainerTwoDrawerTestApp, DrawerDelayed],
317+
declarations: [
318+
DrawerContainerTwoDrawerTestApp,
319+
DrawerDelayed,
320+
DrawerContainerStateChangesTestApp,
321+
],
318322
});
319323

320324
TestBed.compileComponents();
@@ -363,6 +367,47 @@ describe('MatDrawerContainer', () => {
363367

364368
expect(parseInt(contentElement.style.marginLeft)).toBeGreaterThan(0);
365369
}));
370+
371+
it('should recalculate the margin if a drawer is destroyed', fakeAsync(() => {
372+
const fixture = TestBed.createComponent(DrawerContainerStateChangesTestApp);
373+
374+
fixture.detectChanges();
375+
fixture.componentInstance.drawer.open();
376+
fixture.detectChanges();
377+
tick();
378+
fixture.detectChanges();
379+
380+
const contentElement = fixture.debugElement.nativeElement.querySelector('.mat-drawer-content');
381+
const initialMargin = parseInt(contentElement.style.marginLeft);
382+
383+
expect(initialMargin).toBeGreaterThan(0);
384+
385+
fixture.componentInstance.renderDrawer = false;
386+
fixture.detectChanges();
387+
388+
expect(parseInt(contentElement.style.marginLeft)).toBeLessThan(initialMargin);
389+
}));
390+
391+
it('should recalculate the margin if the drawer mode is changed', fakeAsync(() => {
392+
const fixture = TestBed.createComponent(DrawerContainerStateChangesTestApp);
393+
394+
fixture.detectChanges();
395+
fixture.componentInstance.drawer.open();
396+
fixture.detectChanges();
397+
tick();
398+
fixture.detectChanges();
399+
400+
const contentElement = fixture.debugElement.nativeElement.querySelector('.mat-drawer-content');
401+
const initialMargin = parseInt(contentElement.style.marginLeft);
402+
403+
expect(initialMargin).toBeGreaterThan(0);
404+
405+
fixture.componentInstance.mode = 'over';
406+
fixture.detectChanges();
407+
408+
expect(parseInt(contentElement.style.marginLeft)).toBeLessThan(initialMargin);
409+
}));
410+
366411
});
367412

368413

@@ -474,3 +519,19 @@ class DrawerDelayed {
474519
@ViewChild(MatDrawer) drawer: MatDrawer;
475520
showDrawer = false;
476521
}
522+
523+
524+
@Component({
525+
template: `
526+
<mat-drawer-container>
527+
<mat-drawer *ngIf="renderDrawer" [mode]="mode"></mat-drawer>
528+
</mat-drawer-container>`,
529+
})
530+
class DrawerContainerStateChangesTestApp {
531+
@ViewChild(MatDrawer) drawer: MatDrawer;
532+
@ViewChild(MatDrawerContainer) drawerContainer: MatDrawerContainer;
533+
534+
mode = 'side';
535+
renderDrawer = true;
536+
}
537+

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)