Skip to content

Commit d9d9395

Browse files
committed
address comments
1 parent cda9331 commit d9d9395

File tree

3 files changed

+109
-15
lines changed

3 files changed

+109
-15
lines changed

src/lib/sidenav/drawer.ts

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,29 @@
88

99
import {
1010
AfterContentInit,
11+
ChangeDetectionStrategy,
12+
ChangeDetectorRef,
1113
Component,
14+
ContentChild,
1215
ContentChildren,
1316
ElementRef,
17+
EventEmitter,
18+
forwardRef,
19+
Inject,
1420
Input,
21+
NgZone,
22+
OnDestroy,
1523
Optional,
1624
Output,
1725
QueryList,
18-
ChangeDetectionStrategy,
19-
EventEmitter,
2026
Renderer2,
2127
ViewEncapsulation,
22-
NgZone,
23-
OnDestroy,
24-
Inject,
25-
ChangeDetectorRef, ContentChild, forwardRef,
2628
} from '@angular/core';
27-
import {animate, state, style, transition, trigger, AnimationEvent} from '@angular/animations';
28-
import {Directionality, coerceBooleanProperty} from '../core';
29-
import {FocusTrapFactory, FocusTrap} from '../core/a11y/focus-trap';
29+
import {animate, AnimationEvent, state, style, transition, trigger} from '@angular/animations';
30+
import {coerceBooleanProperty, Directionality} from '../core';
31+
import {FocusTrap, FocusTrapFactory} from '../core/a11y/focus-trap';
3032
import {ESCAPE} from '../core/keyboard/keycodes';
31-
import {first, takeUntil, startWith} from '../core/rxjs/index';
33+
import {first, startWith, takeUntil} from '../core/rxjs/index';
3234
import {DOCUMENT} from '@angular/platform-browser';
3335
import {merge} from 'rxjs/observable/merge';
3436
import {Subject} from 'rxjs/Subject';
@@ -62,7 +64,11 @@ export class MdDrawerToggleResult {
6264
encapsulation: ViewEncapsulation.None,
6365
})
6466
export class MdDrawerContent implements AfterContentInit {
65-
/** Margins to be applied to the content. */
67+
/**
68+
* Margins to be applied to the content. These are used to push / shrink the drawer content when a
69+
* drawer is open. We use margin rather than transform even for push mode because transform breaks
70+
* fixed position elements inside of the transformed element.
71+
*/
6672
_margins: {left: number, right: number} = {left: 0, right: 0};
6773

6874
constructor(
@@ -71,7 +77,7 @@ export class MdDrawerContent implements AfterContentInit {
7177
}
7278

7379
ngAfterContentInit() {
74-
this._container._contentMargins.subscribe((margins) => {
80+
this._container._contentMargins.subscribe(margins => {
7581
this._margins = margins;
7682
this._changeDetectorRef.markForCheck();
7783
});
@@ -193,6 +199,10 @@ export class MdDrawer implements AfterContentInit, OnDestroy {
193199
/** @deprecated */
194200
@Output('align-changed') onAlignChanged = new EventEmitter<void>();
195201

202+
/**
203+
* An observable that emits when the drawer mode changes. This is used by the drawer container to
204+
* to know when to when the mode changes so it can adapt the margins on the content.
205+
*/
196206
_modeChanged = new Subject();
197207

198208
get isFocusTrapEnabled() {
@@ -524,6 +534,13 @@ export class MdDrawerContainer implements AfterContentInit {
524534
* sparingly, because it causes a reflow.
525535
*/
526536
private _updateContentMargins() {
537+
// 1. For drawers in `over` mode, they don't affect the content.
538+
// 2. For drawers in `side` mode they should shrink the content. We do this by adding to the
539+
// left margin (for left drawer) or right margin (for right the drawer).
540+
// 3. For drawers in `push` mode the should shift the content without resizing it. We do this by
541+
// adding to the left or right margin and simultaneously subtracting the same amount of
542+
// margin from the other side.
543+
527544
let left = 0;
528545
let right = 0;
529546

src/lib/sidenav/sidenav.spec.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import {Component} from '@angular/core';
2+
import {async, TestBed, ComponentFixture} from '@angular/core/testing';
3+
import {MdSidenav, MdSidenavModule} from './index';
4+
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
5+
import {By} from '@angular/platform-browser';
6+
7+
8+
describe('MdSidenav', () => {
9+
let fixture: ComponentFixture<SidenavWithFixedPosition>;
10+
let sidenavEl: HTMLElement;
11+
12+
beforeEach(async(() => {
13+
TestBed.configureTestingModule({
14+
imports: [MdSidenavModule, NoopAnimationsModule],
15+
declarations: [SidenavWithFixedPosition],
16+
});
17+
18+
TestBed.compileComponents();
19+
20+
fixture = TestBed.createComponent(SidenavWithFixedPosition);
21+
fixture.detectChanges();
22+
23+
sidenavEl = fixture.debugElement.query(By.directive(MdSidenav)).nativeElement;
24+
}));
25+
26+
it('should be fixed position when in fixed mode', () => {
27+
expect(sidenavEl.classList).toContain('mat-sidenav-fixed');
28+
29+
fixture.componentInstance.fixed = false;
30+
fixture.detectChanges();
31+
32+
expect(sidenavEl.classList).not.toContain('mat-sidenav-fixed');
33+
});
34+
35+
it('should set fixed bottom and top when in fixed mode', () => {
36+
expect(sidenavEl.style.top).toBe('20px');
37+
expect(sidenavEl.style.bottom).toBe('30px');
38+
39+
fixture.componentInstance.fixed = false;
40+
fixture.detectChanges();
41+
42+
expect(sidenavEl.style.top).toBeFalsy();
43+
expect(sidenavEl.style.bottom).toBeFalsy();
44+
});
45+
});
46+
47+
48+
@Component({
49+
template: `
50+
<md-sidenav-container>
51+
<md-sidenav
52+
#drawer
53+
[fixedInViewport]="fixed"
54+
[fixedTopGap]="fixedTop"
55+
[fixedBottomGap]="fixedBottom">
56+
Drawer.
57+
</md-sidenav>
58+
<md-sidenav-content>
59+
Some content.
60+
</md-sidenav-content>
61+
</md-sidenav-container>`,
62+
})
63+
class SidenavWithFixedPosition {
64+
fixed = true;
65+
fixedTop = 20;
66+
fixedBottom = 30;
67+
}

src/lib/sidenav/sidenav.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from '@angular/core';
1515
import {MdDrawer, MdDrawerContainer, MdDrawerContent} from './drawer';
1616
import {animate, state, style, transition, trigger} from '@angular/animations';
17+
import {coerceBooleanProperty, coerceNumberProperty} from '@angular/cdk/coercion';
1718

1819

1920
@Component({
@@ -77,19 +78,28 @@ export class MdSidenavContent extends MdDrawerContent {
7778
})
7879
export class MdSidenav extends MdDrawer {
7980
/** Whether the sidenav is fixed in the viewport. */
80-
@Input() fixedInViewport = true;
81+
@Input()
82+
get fixedInViewport() { return this._fixedInViewport; }
83+
set fixedInViewport(value) { this._fixedInViewport = coerceBooleanProperty(value); }
84+
private _fixedInViewport = true;
8185

8286
/**
8387
* The gap between the top of the sidenav and the top of the viewport when the sidenav is in fixed
8488
* mode.
8589
*/
86-
@Input() fixedTopGap = 0;
90+
@Input()
91+
get fixedTopGap() { return this._fixedTopGap; }
92+
set fixedTopGap(value) { this._fixedTopGap = coerceNumberProperty(value); }
93+
private _fixedTopGap = 0;
8794

8895
/**
8996
* The gap between the bottom of the sidenav and the bottom of the viewport when the sidenav is in
9097
* fixed mode.
9198
*/
92-
@Input() fixedBottomGap = 0;
99+
@Input()
100+
get fixedBottomGap() { return this._fixedBottomGap; }
101+
set fixedBottomGap(value) { this._fixedBottomGap = coerceNumberProperty(value); }
102+
private _fixedBottomGap = 0;
93103
}
94104

95105

0 commit comments

Comments
 (0)