web-dev-qa-db-ja.com

Angular2およびng-bootstrapのコンポーネントのNgbTabSetから「select」メソッドにアクセスするにはどうすればよいですか?

Angular 2.3.1およびng-bootstrap 1.0.0-alpha.18を使用します。テンプレート内からではなく、コンポーネントからIDに基づいてプログラムでタブを選択しようとしています。目標はURLからパラメーターを取得し、それを使用して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');
   }
}

これは単にエラーを生成します:

コンソールログエラー

この方法にアクセスするにはどうすればよいですか?

14
bikeguy

Ngb-TabSetを使用したルーティング

AngularJs 1.xでは、ui-routerを使用して名前を設定するのは簡単でした。 Angular 2とNg-Bootstrapではそれほど明白ではありません。逆に、必要なものはネイティブ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]属性という1つの例外を除いて、構成は簡単です。 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には、ルート構成で定義した名前(つまり、data:{name:'followups'})と一致するidセットがあります。

コンポーネントのセットアップ

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は、#tab要素に追加した属性(ngb-tabset)への参照です。

次はconstructorです。ドキュメントでは明らかではありませんが、dataObservable<data>です。値をキャプチャするために、ルートからdataプロパティにサブスクライブしています。

constuctorに続くのはngOnInitです。これはタブにとって重要ではありませんが、タブのルーティングで使用するprospectIdをキャプチャします。ルートに動的データがない場合、これは必要ありません。

最後に、ngAfterViewCheckedがあります。 tabsをルーティングするには、これが最も重要です。ここでは、マークアップからキャプチャしたtabs変数を使用し、選択したタブを変更するために、選択したタブ名をtabsに渡します。

更新

これを適切に機能させるには、ngb-tabsettabChangeイベントにフックするために追加する必要がありました。

HTML:

<ngb-tabset [activeId]="selectedTab" #tabs (tabChange)="onTabChange($event)">

TypeScript:

また、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]);
}
16
Chuck Conway

これは、タブが初期化される前にタブでselectを呼び出しているために発生しています。 NgTabsetは、ビューが初期化された後に初期化されます。ブール値を使用して、selectを呼び出す前に初期化されているかどうかを確認しました。

    tabsInitialized: boolean = false;
    @ViewChild('tabs') public tabs:NgbTabset;

    ngAfterViewInit() {
     this.tabsInitialized = true;
    }



    ngOnChanges(){
     if(this.tabsInitialized){
      this.tabs.select('dashboard');
    }
   }
...
4
hnameer-GRIT

誰かがテンプレートからそれをしたい場合、最良のアプローチは次のとおりです。

<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>
4
Adrita Sharma

要素に参照を置きます

<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の実行をセットに移動しました。

1
misha130

あなたが持っている問題は、イベントループの間違った部分でコードを実行しているためです。 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>

コンポーネントコントローラーts

@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」、
0
Kieran