I don't think this can be done using Material Design Lite, at least not now. I ended up using Angular Material 2 and was able to separate the sidenav into it's own component. View this plunker for an example.
Following is the code in case the link doesn't work.
app.component.html
<my-sidenav></my-sidenav>
app.component.ts
import {Component} from '@angular/core';
import {bootstrap} from '@angular/platform-browser-dynamic';
import {SidenavComponent} from 'sidenav.component.ts';
import {GlueService} from 'glue.service.ts';
@Component({
selector: 'material-app',
templateUrl: 'app.component.html',
directives: [SidenavComponent],
providers: [GlueService]
})
export class AppComponent {
}
bootstrap(AppComponent);
Since the sidenav is an outside container to everything else it has to be loaded first:
sidenav.component.html
<md-sidenav-layout>
<md-sidenav #start [opened]="opened" id="left_sidenav" layout-padding>
<h2>Sidenav</h2>
<button md-raised-button class="md-raised md-primary" (click)="start.close()">Close</button>
</md-sidenav>
<md-content>
<my-content></my-content>
</md-content>
</md-sidenav-layout>
sidenav.component.ts
import {Component, ViewChild} from '@angular/core';
import {MdButton} from '@angular2-material/button';
import {MD_SIDENAV_DIRECTIVES, MdSidenav} from '@angular2-material/sidenav';
import {ContentComponent} from 'content.component.ts';
import {GlueService} from 'glue.service.ts';
@Component({
selector: 'my-sidenav',
templateUrl: 'sidenav.component.html',
directives: [MdButton, MD_SIDENAV_DIRECTIVES, ContentComponent],
providers: []
})
export class SidenavComponent{
opened: false;
@ViewChild('start') sidenavComponent: MdSidenav;
constructor(private glueService: GlueService) {
glueService.toggleConfirmed$.subscribe(
toggle => {
this.toggleLeftNav();
});
}
toggleLeftNav(){
(<MdSidenav>this.sidenavComponent).open();
}
}
The content component contains the header and the content. You could easily split this up into 2 components.
content.component.html
<md-toolbar color="primary">
<button md-raised-button style="color:black;margin:10px" (click)="openLeftNav()">Open Sidenav</button>
Angular Material 2 App
</md-toolbar>
<h2>Content</h2>
content.component.ts
import {Component, OnDestroy} from '@angular/core';
import {MdToolbar} from '@angular2-material/toolbar';
import {MdButton} from '@angular2-material/button';
import { GlueService } from 'glue.service.ts';
@Component({
selector: 'my-content',
templateUrl: 'content.component.html',
directives: [MdToolbar, MdButton]
})
export class ContentComponent implements OnDestroy{
constructor(private glueService: GlueService) { }
openLeftNav(){
this.glueService.confirmToggle(true);
}
}
I created a service (no idea what to call it) that allows the different components to talk to each other. I called it glue.service.ts. I also don't know if this is the BEST way for one component to talk to another although this method was mentioned in Angular 2's cookbook.
glue.service.ts
import { Injectable } from '@angular/core'
import { Subject } from 'rxjs/Subject';
@Injectable()
export class GlueService {
private toggleAnnouncedSource = new Subject<boolean>();
private toggleConfirmedSource = new Subject<boolean>();
// Observable string streams
toggleAnnounced$ = this.toggleAnnouncedSource.asObservable();
toggleConfirmed$ = this.toggleConfirmedSource.asObservable();
// Service message commands
announceToggle(toggle: boolean) {
this.toggleAnnouncedSource.next(toggle)
}
confirmToggle(toggle: boolean) {
this.toggleConfirmedSource.next(toggle);
}
}