It is my app.component.ts:
import { Component } from '@angular/core';
@Component({
templateUrl: 'app/app.component.html',
selector: 'my-app'
})
export class AppComponent {
}
And this is my app.component.html:
<p-tabView>
<p-tabPanel header="Home" leftIcon="fa-bar-chart-o">
<home-app></home-app>
</p-tabPanel>
<p-tabPanel header="Hierarquia" leftIcon="fa-sitemap">
<tree-app></tree-app>
</p-tabPanel>
<p-tabPanel header="Configurações" leftIcon="fa-cog">
<config-app></config-app>
</p-tabPanel>
</p-tabView>
My three components (home, tree and config) are been loaded at the same time when the tabView is loaded. However, I would like that a component was loaded just when its tab was selected. How to do that?
P.S.: if it helps, TabView has an onChange event.
You can use SystemJsNgModuleLoader
which is used in angular2 routing
First you can write component which will load module:
@Component({
selector: 'dynamic-container',
template: `
<template #container></template>
<div *ngIf="!loaded" class="loader"></div>
`,
styles: [`
.loader {
position: relative;
min-height: 100px;
}
.loader:after {
content: 'Loading module. Please waiting...';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
`]
})
export class DynamicContainerComponent implements OnDestroy {
@ViewChild('container', { read: ViewContainerRef }) vcRef: ViewContainerRef;
loaded: boolean;
constructor(private moduleLoader: SystemJsNgModuleLoader) { }
compRef: ComponentRef<any>;
@Input() modulePath: string;
@Input() moduleName: string;
_inited: boolean
set inited(val: boolean) {
if(val) {
this.loadComponent();
}
this._inited = val;
};
get inited() {
return this._inited;
}
loadComponent() {
this.moduleLoader.load(`${this.modulePath}#${this.moduleName}`)
.then((moduleFactory: NgModuleFactory<any>) => {
const vcRef = this.vcRef;
const ngModuleRef = moduleFactory.create(vcRef.parentInjector);
const comp = ngModuleRef.injector.get(LazyLoadConfig).component;
const compFactory = ngModuleRef.componentFactoryResolver.resolveComponentFactory(comp);
this.compRef = vcRef.createComponent(compFactory, 0, ngModuleRef.injector);
this.loaded = true;
});
}
ngOnDestroy() {
this.compRef.destroy();
}
}
And then use it in your component:
@Component({
selector: 'my-app',
template: `
<h2 class="plunker-title">How to lazy load Angular 2 components in a TabView (PrimeNG)?</h2>
<p-tabView (onChange)="handleChange($event)">
<p-tabPanel header="Home" leftIcon="fa-bar-chart-o">
<home-app></home-app>
</p-tabPanel>
<p-tabPanel header="Hierarquia" leftIcon="fa-sitemap">
<dynamic-container modulePath="./src/modules/tree/tree.module" moduleName="TreeModule"></dynamic-container>
</p-tabPanel>
<p-tabPanel header="Configurações" leftIcon="fa-cog">
<dynamic-container modulePath="./src/modules/config/config.module" moduleName="ConfigModule"></dynamic-container>
</p-tabPanel>
</p-tabView>
`
})
export class AppComponent {
@ViewChildren(DynamicContainerComponent) dynamicContainers: QueryList<DynamicContainerComponent>;
handleChange(e) {
let dynamicContainer = this.dynamicContainers.toArray()[e.index - 1];
if (!dynamicContainer || dynamicContainer.inited) return;
// prevent fast clicking and double loading
dynamicContainer.inited = true;
}
}
See also