2016-12-15 4 views
2

Il est mon app.component.ts:Comment charger paresseux Angular 2 composants dans un TabView (PrimeNG)?

import { Component } from '@angular/core'; 

@Component({ 
    templateUrl: 'app/app.component.html', 
    selector: 'my-app' 
}) 
export class AppComponent { 

} 

Et voici ma 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> 

Mes trois composants (maison, arbre et configuration) sont été chargés à la en même temps lorsque la tabView est chargée. Cependant, j'aimerais qu'un composant soit chargé juste quand son onglet a été sélectionné. Comment faire ça?

P.S .: si cela aide, TabView a un événement onChange.

+0

Comment le saviez-vous? –

+0

Bonjour, @RomanC. Pardon. Comment ai-je su quoi? –

+0

* Mes trois composants (home, tree et config) sont chargés en même temps que le tabView * - comment savez-vous quoi? –

Répondre

4

Après beaucoup de recherches, je pouvais résoudre le problème en utilisant routeur. Maintenant, l'application est vraiment rapide.

app.component.ts:

import { Component } from '@angular/core'; 
import { Router } from '@angular/router'; 

@Component({ 
    templateUrl: 'app/app.component.html', 
    selector: 'my-app' 
}) 
export class AppComponent { 

    constructor(
     private router: Router) { 
    } 

    handleChange(e) { 
     let index = e.index; 
     let link; 
     switch (index) { 
      case 0: 
       link = ['/home']; 
       break; 
      case 1: 
       link = ['/hierarquia']; 
       break; 
      case 2: 
       link = ['/config']; 
       break; 
     } 
     this.router.navigate(link); 
    } 
} 

app.component.html:

<div> 
    <p-tabView (onChange)="handleChange($event)"> 
     <p-tabPanel header="Home" leftIcon="fa-bar-chart-o"></p-tabPanel> 
     <p-tabPanel header="Hierarquia" leftIcon="fa-sitemap"></p-tabPanel> 
     <p-tabPanel header="Configurações" leftIcon="fa-cog"></p-tabPanel> 
    </p-tabView> 
</div> 

<router-outlet></router-outlet> 

app.route.ts:

import { NgModule } from '@angular/core'; 
import { Routes, RouterModule } from '@angular/router'; 

import { AppHome } from './app.home'; 
import { AppTree } from './app.tree'; 
import { AppConfig } from './app.config'; 

const routes: Routes = [ 
    { 
     path: 'home', 
     component: AppHome 
    }, 
    { 
     path: 'hierarquia', 
     component: AppTree 
    }, 
    { 
     path: 'config', 
     component: AppConfig 
    }, 
    { 
     path: '', 
     redirectTo: '/home', 
     pathMatch: 'full' 
    }, 
]; 

@NgModule({ 
    imports: [RouterModule.forRoot(routes)], 
    exports: [RouterModule] 
}) 
export class AppRoutingModule { } 

export const routedComponents = [AppHome, AppTree, AppConfig]; 

app.module.ts:

import { NgModule } from '@angular/core'; 
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 
import { HttpModule } from '@angular/http'; 
import { BrowserModule } from '@angular/platform-browser'; 
import 'rxjs/add/operator/toPromise'; 

import { AppConfig } from './app.config'; 
import { AppHeader } from './app.header'; 
import { AppHome } from './app.home'; 
import { AppTree } from './app.tree'; 
import { AppComponent } from './app.component'; 

import { AppRoutingModule, routedComponents } from './app.route'; 

import { InputTextModule, DataTableModule, ButtonModule, DialogModule, TabViewModule, ChartModule, TreeModule, GrowlModule, InputSwitchModule, BlockUIModule, InputMaskModule, DropdownModule } from 'primeng/primeng'; 

@NgModule({ 
    imports: [BrowserModule, FormsModule, ReactiveFormsModule, HttpModule, AppRoutingModule, InputTextModule, DataTableModule, ButtonModule, DialogModule, TabViewModule, ChartModule, TreeModule, GrowlModule, InputSwitchModule, BlockUIModule, InputMaskModule, DropdownModule], 
    declarations: [AppHeader, AppComponent, AppHome, AppTree, AppConfig, routedComponents], 
    bootstrap: [AppHeader, AppComponent] 
}) 
export class AppModule { } 

Dieu merci! =]

+0

Semble parfait, et semble propre et conforme aux normes angulaires 2 par rapport à la première réponse. –

7

Vous pouvez utiliser SystemJsNgModuleLoader qui est utilisé dans angular2 routage

Live Plunker

enter image description here

D'abord, vous pouvez écrire le composant qui module de charge:

@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(); 
    } 
} 

Et puis utilisez dans votre composant:

@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; 
    } 
} 

Voir aussi

+0

Ça m'a beaucoup aidé! –

0

Primview tabview a un attribut "paresseux" qui est par défaut à "faux". Vous pouvez le définir comme suit

<p-tabView [lazy]="true"> 
0

J'ai essayé attribut paresseux qui ne fonctionne pas. Utiliser un routeur et ModuleLoader sont super mais un peu complexes. Si vous voulez garder votre application pas trop complexe, la solution la plus simple est d'utiliser NgIf pour rendre les onglets.

<p-tabView (onChange)="handleChange($event)"> 
    <p-tabPanel header="Home" leftIcon="fa-bar-chart-o"> 
     <home-app *ngIf="activeTab === 0"></home-app> 
    </p-tabPanel> 
    <p-tabPanel header="Hierarquia" leftIcon="fa-sitemap"> 
     <tree-app *ngIf="activeTab === 1"></tree-app> 
    </p-tabPanel> 
    <p-tabPanel header="Configurações" leftIcon="fa-cog"> 
     <config-app *ngIf="activeTab === 2"></config-app> 
    </p-tabPanel> 
</p-tabView> 

Et de définir un indicateur pour rendre l'onglet sélectionné.

handleChange(e) { 
    this.activeTab = e.index; 
}