2016-12-15 7 views
2

Es ist mein app.component.ts:Wie lazy laden Angular 2 Komponenten in einem TabView (PrimeNG)?

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

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

} 

Und das ist mein 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> 

Meine drei Komponenten (zu Hause, Baum und config) werden an die geladen worden Gleichzeitig wenn die tabView geladen wird. Ich möchte jedoch, dass eine Komponente geladen wurde, nur wenn ihre Registerkarte ausgewählt wurde. Wie geht das?

S.S .: Wenn es hilft, hat TabView ein onChange-Ereignis.

+0

Woher wussten Sie das? –

+0

Hallo, @RomanC. Es tut uns leid. Woher wusste ich was? –

+0

* Meine drei Komponenten (home, tree und config) wurden zur selben Zeit geladen, als die tabView geladen wurde * - woher weißt du was? –

Antwort

4

Nach viel Forschung, ich das Problem mit Router lösen könnte. Jetzt ist die Anwendung sehr schnell.

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 { } 

Danke Gott! =]

+0

Scheint perfekt, und sieht sauber und inline mit eckigen 2 Standards im Vergleich zur ersten Antwort. –

7

können Sie SystemJsNgModuleLoader verwenden, die in angular2

Live Plunker Routing verwendet wird

enter image description here

Zuerst Komponente schreiben kann, das Modul laden:

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

Und dann verwenden es in Ihrer Komponente:

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

Siehe auch

+0

Es hat mir sehr geholfen! –

0

Die Primeng Tabview hat ein Attribut "faul", das standardmäßig auf "false" gesetzt ist. Sie können es wie folgt

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

ich faul Attribut versucht haben, das funktioniert nicht. Router und ModuleLoader sind großartig, aber ein bisschen komplex. Wenn Sie Ihre Anwendung nicht zu komplex halten möchten, ist die einfachste Lösung, NgIf zum Rendern von Registerkarten zu verwenden.

<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> 

Und definieren Sie ein Flag, um die ausgewählte Registerkarte zu rendern.

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