Есть довольно много вопросов, которые вы задали.Вот решение, если вы заинтересованы в динамической загрузке компонентов до SideNav
контента.
sidenav.service.ts
import {
Injectable,
Component,
ComponentRef,
NgModule,
NgModuleRef,
Injector,
Compiler,
ViewContainerRef
} from '@angular/core';
import {Subject} from 'rxjs';
@Injectable()
export class SidenavService {
public subject = new Subject<string>();
private sidenavVCRef: ViewContainerRef;
constructor(private compiler: Compiler, private injector: Injector,
private ngModuleRef: NgModuleRef<any>) {}
// getSidenavVCRef() { return this.sidenavVCRef; }
setSidenavVCRef(vc: ViewContainerRef) { this.sidenavVCRef = vc; }
publish(eventName: string, componentName?: string) {
console.log("qua", this.subject, eventName);
if (componentName) {
this.loadComponent(componentName).then(() => {
this.subject.next(eventName);
});
} else {
this.subject.next(eventName);
}
}
// Create component on the fly, and insert to the view container
private loadComponent(name: string): Promise<boolean> {
// create component and module on the fly
const template = `<span>I am ${name}</span>`;
const tmpComp = Component({template : template})(class {});
const tmpModule = NgModule({declarations : [ tmpComp ]})(class {});
// compile the created module and component,
// and get a hold of it with a componentRef
return new Promise(resolve => {
this.compiler.compileModuleAndAllComponentsAsync(tmpModule)
.then(factories => {
// Compiler will return all factories for corresponding components
// to be created
// Just take the first one as it is the only one.
const f = factories.componentFactories[0];
// create (component) view from its factory and return componentRef
const compRef = f.create(this.injector, [], null, this.ngModuleRef);
// just detach all previous views from view container
this.sidenavVCRef.detach();
// insert it to its view container
this.sidenavVCRef.insert(compRef.hostView);
resolve(true);
})
.catch(error => { console.log(error); });
});
}
}
navigator.component.ts
import {
Component,
OnInit,
ViewChild,
ViewContainerRef,
AfterViewInit
} from '@angular/core';
import {SidenavService} from '../sidenav.service';
@Component({
selector : 'app-navigator',
templateUrl : './navigator.component.html',
styleUrls : [ './navigator.component.css' ]
})
export class NavigatorComponent implements OnInit,
AfterViewInit {
@ViewChild('sidenav') sidenav;
@ViewChild('vcDynamicComp', {read : ViewContainerRef}) vc: ViewContainerRef;
constructor(private sidenavService: SidenavService, ) {}
ngOnInit() {
this.sidenavService.subject.subscribe((value) => {
console.log("value:", value);
switch (value) {
case 'open':
this.openSidenav();
break;
case 'close':
this.closeSidenav();
break;
default:
break;
}
});
}
ngAfterViewInit() {
// set sidenav view container reference at as the first thing when view is
// available
this.sidenavService.setSidenavVCRef(this.vc);
}
private openSidenav() { this.sidenav.toggle(); }
private closeSidenav() { this.sidenav.close(); }
openSN() { this.sidenavService.publish('open', 'Component A'); }
}
навигатор.component.html
<mat-sidenav-container class="example-container">
<mat-sidenav #sidenav mode="side" opened="false">
Sidenav content
<div #vcDynamicComp></div>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar>My App
<span style=" flex: 1 1 auto"></span>
<button mat-raised-button routerLink="/page1">Page1</button>
<button mat-raised-button routerLink="/page2">Page2</button>
<button mat-raised-button color="primary" (click)="openSN()">Open sidenav</button>
</mat-toolbar>
<main>
<router-outlet></router-outlet>
</main>
</mat-sidenav-content>
</mat-sidenav-container>
Вот рабочий пример при стеке блиц