web-dev-qa-db-ja.com

Typescriptエラー:@viewChild undefined

Ionic Tabsドキュメントのtabs.tsでselect()メソッドを使用してみました。しかし、実行しようとすると、「select is undefined」と表示され、 console.log(tabs)を試したところ、viewChildは実際には空/未定義です。viewChildが未定義である理由を検索しようとしましたが、その理由を実際には理解できませんでした。

ionic tabsドキュメントへのリンク: https://ionicframework.com/docs/api/components/tabs/Tabs/

tabs.html

<ion-tabs #tabs>
  <ion-tab [root]="tab1Root" tabTitle="Request" tabIcon="alert"></ion-tab>
  <ion-tab [root]="tab2Root" [rootParams]="detailParam" tabTitle="Pending" 
   tabIcon="repeat"></ion-tab>
  <ion-tab [root]="tab3Root" tabTitle="Completed" tabIcon="done-all"></ion-
   tab>
  <ion-tab [root]="tab4Root" tabTitle="Profile" tabIcon="person"></ion-tab>  
</ion-tabs>

tabs.ts

import { Component, ViewChild } from '@angular/core';
import { NavController, NavParams, AlertController, Tabs } from 'ionic-
angular';
import { PendingJobPage } from '../pending-job/pending-job';
import { CompletedJobPage } from '../completed-job/completed-job';
import { RequestPage } from '../request/request';
import { ProfilePage } from '../profile/profile';

@Component({
  templateUrl: 'tabs.html'
})
export class TabsPage {

  @ViewChild('tabs') tabRef: Tabs;
  pending: any;
  apply: boolean;
  detailsParam: any;

  tab1Root = RequestPage;
  tab2Root = PendingJobPage;
  tab3Root = CompletedJobPage;
  tab4Root = ProfilePage;

  constructor(public navParams: NavParams, public navCtrl: NavController) {
    this.pending = this.navParams.get('param1');
    this.apply = this.navParams.get('apply');
    this.detailsParam = this.navParams.data;
    console.log("a = ", this.tabRef);

    if(this.apply === true){
      this.navCtrl.parent.select(1);
    }
    else{
      this.navCtrl.parent.select(0);
    }
  }
}

Angular Docs で見ることができるように、

ViewChildは、ビューが初期化された後に設定されます

そして

ViewChildは、ビューがチェックされた後に更新されます

export class AfterViewComponent implements  AfterViewChecked, AfterViewInit {

  ngAfterViewInit() {
    // viewChild is set after the view has been initialized <- Here!
  }

  ngAfterViewChecked() {
    // viewChild is updated after the view has been checked <- Here!
  }

  // ...

}

したがって、コードの問題は、コンストラクターの実行時にビューが初期化されていないことです。タブと相互作用するすべてのコードをngAfterViewInitライフサイクルフックに配置する必要があります。

  ngAfterViewInit() {
    // Now you can use the tabs reference
    console.log("a = ", this.tabRef);
  }

Ionicカスタムライフサイクルイベントを使用するだけの場合は、ionViewDidEnterフックを使用する必要があります。

export class TabsPage {

@ViewChild('myTabs') tabRef: Tabs;

ionViewDidEnter() {
    // Now you can use the tabs reference
    console.log("a = ", this.tabRef);
 }

}
6
sebaferreras