如何在TabView(PrimeNG)中加载Angular 2组件?

问题描述:

这是我app.component.ts:如何在TabView(PrimeNG)中加载Angular 2组件?

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

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

} 

这是我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> 

我的三个组成部分(家庭,树和配置)在被加载同时加载tabView。但是,我希望组件在选择其选项卡时加载。怎么做?

P.S .:如果有帮助,TabView有一个onChange事件。

+0

你是怎么知道的? –

+0

嗨,@罗曼C。抱歉。我怎么知道什么? –

+0

*在加载tabView的同时,我的三个组件(home,tree和config)被加载* - 你是怎么知道的? –

见大量的研究后,我可以解决使用路由器问题。现在应用程序非常快。

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

谢天谢地! =]

+0

看起来很完美,与第一个答案相比,它看上去很干净,并且与角度2标准一致。 –

您可以使用SystemJsNgModuleLoader这是在angular2路由

Live Plunker

enter image description here

首先,你可以写组件将加载模块一起使用:

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

然后用它在你的组件中:

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

+0

它帮了我很多! –

Primeng tabview有一个默认为“false”的“懒”属性。 您可以将其设置如下

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

我试过懒惰的属性,它不起作用。使用路由器和ModuleLoader很棒,但有点复杂。如果你想让你的应用程序不太复杂,最简单的解决方案是使用NgIf来渲染制表符。

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

并定义一个标志来呈现选定的选项卡。

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