diff --git a/src/demo-app/sidenav/sidenav-demo.html b/src/demo-app/sidenav/sidenav-demo.html index bdddd69c381a..5e979e9b7576 100644 --- a/src/demo-app/sidenav/sidenav-demo.html +++ b/src/demo-app/sidenav/sidenav-demo.html @@ -36,7 +36,7 @@

My Content

-

Sidenav Already Opened

+

Drawer Already Opened

@@ -48,6 +48,18 @@

Sidenav Already Opened

+

Responsive Drawer

+ + + + Drawer + + +
+ +
+
+

Dynamic Position Sidenav

diff --git a/src/lib/sidenav/drawer.ts b/src/lib/sidenav/drawer.ts index 4a00b86a035f..6be957af171b 100644 --- a/src/lib/sidenav/drawer.ts +++ b/src/lib/sidenav/drawer.ts @@ -25,10 +25,13 @@ import { ChangeDetectorRef, } from '@angular/core'; import {animate, state, style, transition, trigger, AnimationEvent} from '@angular/animations'; -import {Directionality, coerceBooleanProperty} from '../core'; +import {Directionality, coerceBooleanProperty, coerceNumberProperty} from '../core'; import {FocusTrapFactory, FocusTrap} from '../core/a11y/focus-trap'; import {ESCAPE} from '../core/keyboard/keycodes'; -import {first, takeUntil, startWith} from '../core/rxjs/index'; +import {first, takeUntil, startWith, auditTime} from '../core/rxjs/index'; +import {Subscription} from 'rxjs/Subscription'; +import {of as observableOf} from 'rxjs/observable/of'; +import {fromEvent} from 'rxjs/observable/fromEvent'; import {DOCUMENT} from '@angular/platform-browser'; import {merge} from 'rxjs/observable/merge'; @@ -325,6 +328,31 @@ export class MdDrawerContainer implements AfterContentInit { /** Event emitted when the drawer backdrop is clicked. */ @Output() backdropClick = new EventEmitter(); + /** Breakpoint width (in px) at which the sidenav collapses. */ + + @Input() + get breakpointWidth() { return this._breakpointWidth; } + set breakpointWidth(v: number) { + this._breakpointWidth = coerceNumberProperty(v, this._breakpointWidth); + } + private _breakpointWidth: number; + + /** Whether the drawer changes modes when collapsing. */ + @Input() + get breakpointChangeMode() { return this._breakpointChangeMode; } + set breakpointChangeMode(value: boolean) { + this._breakpointChangeMode = coerceBooleanProperty(value); + } + private _breakpointChangeMode = true; + + /** + * Responsively toggle the drawer using the breakpoint. + * Note that this only works when the window is rezied. + * If you resize it some other way, call _updateDrawer(). + */ + private _updateDrawerSubscription: Subscription | null = null; + private _updateDrawer() {} + /** The drawer at the start/end position, independent of direction. */ private _start: MdDrawer | null; private _end: MdDrawer | null; @@ -359,6 +387,32 @@ export class MdDrawerContainer implements AfterContentInit { this._watchDrawerPosition(drawer); }); }); + + const resize = typeof window !== 'undefined' ? + auditTime.call(fromEvent(window, 'resize'), 150) : + observableOf(null); + + this._updateDrawer = () => { + if (this._element.nativeElement.offsetWidth < this.breakpointWidth) { + if (this.breakpointChangeMode) { + this._drawers.forEach(drawer => drawer.mode = 'over'); + } + this.close(); + } else { + if (this.breakpointChangeMode) { + this._drawers.forEach(drawer => drawer.mode = 'side'); + } + this.open(); + } + }; + this._updateDrawerSubscription = startWith.call(resize, null).subscribe(this._updateDrawer); + + } + + ngOnDestroy() { + if (this._updateDrawerSubscription) { + this._updateDrawerSubscription.unsubscribe(); + } } /** Calls `open` of both start and end drawers */