我正在尝试在选项卡中加载组件。在单击特定选项卡时,我需要加载特定的组件。但是它在导航到该组件时加载所有组件。
.html
<p-tabView orientation="left" (onChange)="onTabChange($event)">
<p-tabPanel *ngFor="let item of items" style="border: solid 1px; padding: 20px;margin: 20px;" [selected]="activeTabIndex==i">
<strong> When you click here,
I should load the <span style="color:red"> {{item.name}} </span>
component below</strong> <br />
<ng-container *ngComponentOutlet="childmap[item.name] "></ng-container>
<br />
</p-tabPanel>
</p-tabView>
.ts
@Component({
selector: 'my-app',
templateUrl:'dashboard.html'
`
})
export class App {
activeTabIndex: number = 0;
childmap = {
'slider': sliderComponent,
'user': usersComponent,
'alert danger': AlertDangerComponent
}
items:Array<any> = [
{
name: 'slider'
},
{
name: 'user'
},
{
name: 'alert danger'
}
]
onTabChange(event: any) {
this.activeTabIndex = event.index;
}
}
有很多解决方案。请使用ngComponentOutlet
。
这是tab-container:
import {Component, Input} from '@angular/core'
import {TabContentAlternativeComponent} from './tab-content-alternative.component'
import {BasicContent} from './basic-content'
@Component({
selector: 'tab',
template: ''
})
export class TabComponent {
@Input() title: string;
@Input() contentRef: BasicContent;
active = false;
}
这是一个非常简单的组件,知道其自己的选项卡名称,一个活动状态和身体组件参考,当有人选择标签时应加载。
然后,我们创建几个身体组件,这些组件将动态加载:
export class BasicContent {
}
组件1
import {Component, Input, OnInit} from '@angular/core'
import {BasicContent} from './basic-content'
@Component({
selector: 'tab-content',
template: `
<p>Hey</p>
`,
})
export class TabContentComponent extends BasicContent {
}
组件2
import {Component, Input} from '@angular/core'
import {BasicContent} from './basic-content'
@Component({
selector: 'tab-content-alternative',
template: `
<p>Hey, this is an alternative content</p>
`,
})
export class TabContentAlternativeComponent extends BasicContent {
}
这是带有标签渲染的选项卡 - 容器组件,也是动态车身组件的空占位符:
import {AfterContentInit, Component, ContentChildren, QueryList} from '@angular/core'
import {TabComponent} from './tab.component'
import {BasicContent} from 'basic-content'
import 'rxjs/Rx';
import {Observable, BehaviorSubject} from 'rxjs/Rx';
@Component({
selector: 'tab-container',
template: `
<div class="tab-header">
<div class="tab" *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active">{{tab.title}}</div>
</div>
<div class="tab-content">
<ng-container *ngComponentOutlet="content | async"></ng-container>
</div>
`,
})
export class TabContainerComponent implements AfterContentInit {
@ContentChildren(TabComponent) tabs: QueryList<TabComponent>;
private contentSbj = new BehaviorSubject<BasicContent>(null);
content = this.contentSbj.asObservable();
ngAfterContentInit() {
const activeTabs = this.tabs.filter((tab) => tab.active);
if (activeTabs.length === 0) {
this.selectTab(this.tabs.first);
}
}
selectTab(tab: TabComponent) {
this.tabs.toArray().forEach(tab => tab.active = false);
tab.active = true;
this.contentSbj.next(tab.contentRef);
}
}
titlemapping
import {TabContentComponent} from './tab-content.component';
import {TabContentAlternativeComponent} from './tab-content-alternative.component';
interface TitleMapping {
title: string;
contentComponent: BasicContent;
}
export const allTabs: TitleMapping[] = [
{title: "Tab 1", contentComponent: TabContentComponent},
{title: "Tab 2", contentComponent: TabContentAlternativeComponent},
{title: "Tab 3", contentComponent: TabContentComponent}
]
这就是可以在某些父组件中使用的方式:
import {TabContentComponent} from './tab/tab-content.component'
import {TabContentAlternativeComponent} from './tab/tab-content-alternative.component'
@Component({
selector: 'my-app',
template: `
<tab-container>
<tab title="Tab 1" [contentRef]="normalContent"></tab>
<tab title="Tab 2" [contentRef]="alternativeContent"></tab>
</tab-container>
`,
})
export class App {
normalContent = TabContentComponent;
alternativeContent = TabContentAlternativeComponent;
}
这里正在工作plunkr
我已经将其用于我的项目,并且可以正常工作作为您的要求。
您正在做的事情基本上是在尝试编写自己的路由器。Primeng TabView的构建是为了加载菜单,首先在初始化时首先将所有选项卡中的内容放在其顶部。但是,在菜单下,有TabMenu实际上是您想要的。关键区别在于菜单允许您的列表为benuitems,其中可能包括路由链接作为参数。
这里有一篇很棒的文章,解释了我更喜欢正式文档的细节。您应该首先了解这一点,然后看看Primeng如何实现一种方便的方式,如果您提供RouterLink,则如何为您构建这些链接。(有关Menuitem模型的更好文档,请参见Menuitems链接。从您的代码中,我无法确定您是否处于最高组件,但我认为您正在寻找的是这些行。此解决方案使用子路由这更复杂,但一个更有用的示例。这是假设您将AppComponent设置为顶级组件,仅在模板中使用<router-outlet></router-outlet>
。这将使您的仪表板组件作为空根重定向到仪表板。
app.module.ts
const myDefinedRoutes: Routes = [
{path: '', redirectTo: 'dashboard', pathMatch: 'full'},
{path: 'dashboard', component: DashboardComponent, children: [
{path: 'slider', component: SliderComponent},
{path: 'user', component: UserComponent},
{path: 'alert', component: AlertDangerComponent},
]
}
]
@NgModule({
// Add this line to imports
RouterModule.forRoot(myDefinedRoutes)
})
export class AppModule {}
dashboard.component.ts
@Component({
selector: 'my-app',
template:`
<p-tabMenu [model]="items"></p-tabMenu>
<router-outlet></router-outlet>
`
})
export class App implements OnInit {
ngOnInit() {
this.items = [
{label: "Slider", routerLink: ['/dashboard', 'slider']},
{label: "User", routerLink: ['/dashboard', 'user']},
{label: "Danger", routerLink: ['/dashboard', 'alert']},
];
this.activeItem = this.items[1]
}
}
请确保在仪表板组件中也将路由器输出包装在仪表板组件中,因为其他组件是孩子的,这意味着您将需要另一个插座,因为第一个插座仍在包含仪表板组件,并且在仪表板组件中,您正在显示其他三个组件之一。