web-dev-qa-db-ja.com

タグが `* ngIf = true`にある場合にのみコンポーネントを初期化する方法は?

更新:
GünterZöchbauerは、完璧に機能する非常に許容できる回答を提供しました(そしてありがとうございます!)。しかし、私がやっていることが、求める結果を得る正しい方法であるかどうかを確認する質問がまだあります。コンテキストを以下に示します。
親ビューのカスタムタグで期待するのは、_*ngIf_条件がfalseの場合、コンポーネントがまったく読み込まれない(またはほとんどの場合)ことです。 DOMにない場合でも(条件がfalseであるため)、ロードされるのは正常ですか?コンポーネントのテンプレート(およびそのクラスのロジック)を親コンポーネントのテンプレートに埋め込むためのより良い方法はありますか?

元の投稿

私はAngular 2を初めて使用するので、これまでのところ、Spotify APIに基づく小さな曲トラックメタデータアプリケーションの開発をとても楽しんでいます。

TL; DR:対応するHTMLタグ(_@Component_のselectorプロパティで定義)の場合にのみコンポーネントを初期化する方法_*ngIf="true"_?


しかし、もちろん私は困難に直面しています!このコンポーネントTrackDetailComponentがテンプレートにあり、そのテンプレートに他の2つのコンポーネントを含めたいと思います。ボタンをクリックすると、1つの内部コンポーネントから別の内部コンポーネントに切り替わります。
テンプレートは次のようになります(現時点では2つの内部コンポーネントの1つしか開発していないため、2つ目のコンポーネントの代わりにプレースホルダーを使用していることに注意してください)。

_<div id="view">
    <tig-track-info *ngIf="childView == TrackDetailView.InfoView" [track]="track"></tig-track-info>
    <p *ngIf="childView == TrackDetailView.LyricsView">Here go the lyrics</p>
</div>
_

ご覧のとおり、内部コンポーネント(TrackInfoComponentという名前)には入力パラメーターがあります。そのコンポーネントの抜粋を次に示します。

_@Component({
    selector: "tig-track-info",
    templateUrl: "app/components/track-info/track-info.component.html",
    styleUrls: ["app/components/track-info/track-info.component.css",
                "app/shared/animations.css"]
})
export class TrackInfoComponent implements OnInit {
    private _trackId: string = null;
    @Input() 
    track: Track = null;
    previewAudio: any = null; // The Audio object is not yet defined in TypeScript
    albumArtworkLoaded: boolean = false;
    ...
}
_

私の本当の問題は、他のTrackInfoComponentを埋め込むことではありませんが、それらを同期することです。 TrackDetailComponentはAPIを非同期で呼び出し、次にtrackプロパティを初期化します。しかし、TrackInfoComponentもその仕事をするためにtrackを初期化する必要があります。そうしないと、null参照例外が発生します(これは論理的です)。

ngOnInit()で子コンポーネントデータを設定し、その親のテンプレートの_*ngIf_をtrueに設定してみましたが、trackの準備ができていて、ngOnInit()は、DOM要素_tig-track-info_が_*ngIf_で表示されない場合でも、すぐに呼び出されます。

子コンポーネントでイベントまたは独自のinitメソッドを使用して、準備ができたときにのみ呼び出すことができると思いますが、Angular 2を使用してそれを行うより良い方法があるかどうか知りたいですコンポーネントライフサイクルフック、またはそのために推奨されるその他のメソッド。誰かそれについて何か考えがありますか?

ありがとうございました :-)

12
Jeahel

テンプレートのバインディング `[track] =" ... "によって@Input()プロパティ値が変更されるたびに呼び出される OnChanges を使用できます。

  export class TrackInfoComponent implements OnChanges {
    ngOnChanges(changes: SimpleChanges) {
      if(this.track) {
        ...
      }
    }
  }
12

1)最初のステップ

import { Component, OnInit, ChangeDetectorRef } from '@angular/core';

コードにChangeDetectorRefを追加する

2)2番目のステップ

constructor(private changeDetector : ChangeDetectorRef){
}

3)* ngIf = "condition"に変化があった場合、つまり条件がtrueになった場合はいつでも、

  if(true==condition){
     this.changeDetector.detectChanges();
  }

4)これにより、htmlテンプレートがレンダリングされます。

それがあなたのために働くなら、あなたはこれを試すことができます。

0