2016-12-15 3 views
2

Это мой app.component.ts:Как ленивая загрузка Угловые 2 компонента в TabView (PrimeNG)?

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

Hi, @ RomanC. Сожалею. Откуда я знаю, что? –

+0

* Мои три компонента (дом, дерево и конфиг) загружаются одновременно с загрузкой tabView * - как вы знаете, что? –

ответ

4

После долгих исследований, я мог бы решить эту проблему, используя маршрутизатор. Теперь приложение работает очень быстро.

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

Кажется совершенным, и выглядит чисто и inline с угловыми 2 стандартами по сравнению с первым ответом. –

7

Вы можете использовать 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

Это очень помогло мне! –

0

Primeng tabview имеет «ленивый» атрибут, который по умолчанию равен «false». Вы можете установить его следующим образом

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

Я попытался ленивый атрибут, который не работает. Использование маршрутизатора и 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; 
} 
Смежные вопросы