[英]How can I access the 'select' method from NgbTabSet in the component in Angular2 and ng-bootstrap?
使用Angular 2.3.1和ng-bootstrap 1.0.0-alpha.18。 我試圖以編程方式從組件中選擇基於ID的選項卡,而不是從模板中選擇。 目標是從URL中提取param並使用它來選擇ngOnInit中的選項卡
模板
<section id="policy-terms">
<ngb-tabset>
<ngb-tab title="Terms and Privacy" id="terms">
<template ngbTabContent>
<div class="container page-content">
</div>
</template>
</ngb-tab>
<ngb-tab title="Company Policy" id="policy">
<template ngbTabContent>
<div class="container page-content">
</div>
</template>
</ngb-tab>
</ngb-tabset>
</section>
和組件代碼:
import { Component, OnInit } from '@angular/core';
import { NgbTabset } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-policy-terms',
templateUrl: './policy-terms.component.html',
styleUrls: ['./policy-terms.component.scss'],
providers: [
NgbTabset
]
})
export class PolicyTermsComponent implements OnInit {
constructor(
public tabset: NgbTabset
) { }
ngOnInit() {
this.tabset.select('policy');
}
}
這只會產生一個錯誤:
我該如何訪問此方法?
在AngularJs 1.x中使用ui-router設置名稱路由是直截了當的。 在帶有Ng-Bootstrap的Angular 2中,它並不那么明顯。 從好的方面來說,您需要的是原生的Angular 2庫。
export const appRoutes: Routes =
[
{ path: 'prospect/:prospectid/details', component: ProspectTabsView, data:{name:'details'} },
{ path: 'prospect/:prospectid/appointments', component: ProspectTabsView, data:{name:'appointments'} },
{ path: 'prospect/:prospectid/followups', component: ProspectTabsView, data:{name:'followups'} },
{ path: 'prospect/:prospectid/contacts', component: ProspectTabsView, data:{name:'contacts'} },
{ path: '', component: DashboardView },
{ path: '**', redirectTo: '', pathMatch: 'full'}
];
配置很簡單,只有一個例外: [data]屬性。 您會注意到它有一個名為name
的鍵。 這是路線的名稱。 將其視為數據包作為數據包。 您可以添加多個路徑名稱。
<ngb-tabset #tabs>
<ngb-tab id="details">
<ng-template ngbTabTitle>
<a [routerLink]="['/prospect', prospectId, 'details']">Details</a>
</ng-template>
<ng-template ngbTabContent>
</ng-template>
</ngb-tab>
<ngb-tab id="contacts">
<ng-template ngbTabTitle>
<a [routerLink]="['/prospect',prospectId,'contacts']">Contacts</a>
</ng-template>
<ng-template ngbTabContent>
</ng-template>
</ngb-tab>
<ngb-tab id="appointments">
<ng-template ngbTabTitle>
<a [routerLink]="['/prospect', prospectId, 'appointments']">Appointments</a>
</ng-template>
<ng-template ngbTabContent>
</ng-template>
</ngb-tab>
<ngb-tab id="followups">
<ng-template ngbTabTitle>
<a [routerLink]="['/prospect', prospectId, 'followups']">Follow Ups</a>
</ng-template>
<ng-template ngbTabContent>
</ng-template>
</ngb-tab>
</ngb-tabset>
上面的標簽標記沒有什么神奇之處,你需要注意幾件事:首先是在ngb-tabset
元素中,我們已經聲明了變量#tab
。 我們稍后會在組件中使用#tab
。 其次,每個nbg-tab
都有一個id
集,它與我們在路由配置中定義的名稱相匹配(即data:{name:'followups'}
)。
import {
AfterViewChecked, Component, OnInit,
ViewChild
} from '@angular/core';
import '../../assets/css/styles.css';
import {ActivatedRoute} from "@angular/router";
import {NgbTabset} from "@ng-bootstrap/ng-bootstrap";
@Component({
templateUrl: './tabs.view.html'
})
export class ProspectTabsView implements OnInit, AfterViewChecked{
prospectId: number;
selectedTab:string;
@ViewChild('tabs')
private tabs:NgbTabset;
constructor(private route: ActivatedRoute) {
this.route.data.subscribe(d=>{
this.selectedTab = d.name;
});
}
ngOnInit(): void {
this.route.params.subscribe(
params => {
this.prospectId = +params['prospectid'];
}
);
}
ngAfterViewChecked(): void {
if(this.tabs) {
this.tabs.select(this.selectedTab);
}
}
}
本練習中最難的部分是使執行順序正確。 如果不正確,則在操作之前不會初始化集合或屬性。 我們將從課堂頂端開始,向下工作。
首先,我們有變量。 prospectId
是數據的主鍵, selectedTab
是當前所選選項卡的名稱,最后,我們有tabs
變量。 tabs
是對我們添加到ngb-tabset
元素的屬性( #tab
)的引用。
接下來是constructor
。 它在文檔中並不明顯,但data
是Observable<data>
。 要捕獲該值,我們將訂閱路由中的data
屬性。
constuctor
函數之后是ngOnInit
。 這對選項卡並不重要,但它確實捕獲了我們在選項卡路由中使用的prospectId。 如果您的路線中沒有任何動態數據,那么您不需要這樣。
最后,我們有ngAfterViewChecked
。 對於路由tabs
,這是最重要的。 這里我們使用從標記中捕獲的tabs
變量,然后我們將選定的選項卡名稱傳遞給選項tabs
以更改選定的選項卡。
為了使其正常工作,我不得不添加鈎子到tabChange
ngb-tabset
上的tabChange
事件。
<ngb-tabset [activeId]="selectedTab" #tabs (tabChange)="onTabChange($event)">
此外,我不得不在onTabChange函數中硬編碼路由。
onTabChange($event: NgbTabChangeEvent) {
let routes = {
details: `/prospect/${this.prospectId}/details`,
appointments: `/prospect/${this.prospectId}/appointments`,
followups: `/prospect/${this.prospectId}/followups`,
notes: `/prospect/${this.prospectId}/notes`,
dials: `/prospect/${this.prospectId}/dials`,
};
this.router.navigateByUrl(routes[$event.nextId]);
}
如果有人想從模板中做到這一點,最好的方法是:
<ngb-tabset #tabRef="ngbTabset">
<ngb-tab title="Tab-1" id="tab1">
<ng-template ngbTabContent>
<p> Tab 1 Content</p>
</ng-template>
</ngb-tab>
<ngb-tab title="Tab-2" id="tab2">
<ng-template ngbTabContent>
<p> Tab 2 Content</p>
</ng-template>
</ngb-tab>
</ngb-tabset>
<div>
<button class="btn" (click)="tabRef.select('tab2')">Select tab with id tab2</button>
</div>
發生這種情況的原因是,在標簽初始化之前,您正在調用選項卡上的選項。 在視圖初始化之后初始化NgTabset。 我在調用select之前使用了一個布爾值來查看它們是否已被初始化。
tabsInitialized: boolean = false;
@ViewChild('tabs') public tabs:NgbTabset;
ngAfterViewInit() {
this.tabsInitialized = true;
}
ngOnChanges(){
if(this.tabsInitialized){
this.tabs.select('dashboard');
}
}
...
對元素進行引用
<ngb-tabset #tabs>
使用ViewChild控制選項卡
export class PolicyTermsComponent implements OnInit {
private tabs:NgbTabset;
@ViewChild('tabs') public set _tabs(tabs: NgbTabset)
{
if(!tabs) return;
this.tabs = _tabs;
this.tabs.select('policy');
}
}
我將select的執行移動到一個集合,以確保頁面正確創建了tabs組件,並且可以引用和使用它。
您遇到的問題是因為您在事件循環的錯誤部分執行代碼。 您可以使用await/async
將活動選項卡的設置推送到事件循環中的其他微任務
// ... other stuff
{ path: ":id/:tabName", component: ViewTabsComponent },
// ... other stuff
<ngb-tabset #myTabs>
<ngb-tab title="Terms and Privacy" id="terms">
<template ngbTabContent>
<p>content</p>
</template>
</ngb-tab>
<ngb-tab title="Company Policy" id="policy">
<template ngbTabContent>
<p>other content<\p>
</template>
</ngb-tab>
</ngb-tabset>
@ViewChild("myTabs", { static: true, read: NgbTabset }) myTabs: NgbTabset;
async ngOnInit() {
const params = await this.route.paramMap
.pipe(
map((params: ParamMap) => ({ tabName: params.get("tabName") })),
take(1) // <-- force to complete
).toPromise();
this.myTabs.select(`${params.tabName}`);
}
這是合作的
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.