簡體   English   中英

如何從Angular2和ng-bootstrap中的組件中的NgbTabSet訪問'select'方法?

[英]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');
   }
}

這只會產生一個錯誤:

控制台日志錯誤

我該如何訪問此方法?

使用Ngb-TabSet進行路由

在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的鍵。 這是路線的名稱。 將其視為數據包作為數據包。 您可以添加多個路徑名稱。

設置TabSet標記

<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 它在文檔中並不明顯,但dataObservable<data> 要捕獲該值,我們將訂閱路由中的data屬性。

constuctor函數之后是ngOnInit 這對選項卡並不重要,但它確實捕獲了我們在選項卡路由中使用的prospectId。 如果您的路線中沒有任何動態數據,那么您不需要這樣。

最后,我們有ngAfterViewChecked 對於路由tabs ,這是最重要的。 這里我們使用從標記中捕獲的tabs變量,然后我們將選定的選項卡名稱傳遞給選項tabs以更改選定的選項卡。

更新

為了使其正常工作,我不得不添加鈎子到tabChange ngb-tabset上的tabChange事件。

HTML:

<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將活動選項卡的設置推送到事件循環中的其他微任務

路線設置.ts

// ... other stuff
{ path: ":id/:tabName", component: ViewTabsComponent },
// ... other stuff

html /標記

<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}`);
}

這是合作的

  • “@ ng-bootstrap / ng-bootstrap”:“^ 5.0.0”,
  • “@ angular / common”:“^ 8.0.0”,

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM