私は親コンポーネント( CategoryComponent )、子コンポーネント( videoListComponent )、そしてApiServiceを持っています。
私はこの作業中の罰金のほとんどを持っています、すなわち、各コンポーネントはjson apiにアクセスして、観測可能なものを通してその関連データを得ることができます。
現在、ビデオリストコンポーネントはすべてのビデオを取得するだけです。これを特定のカテゴリのビデオのみにフィルタしたいのですが、@Input()
を介してcategoryIdを子に渡すことでこれを実現しています。
CategoryComponent.html
<video-list *ngIf="category" [categoryId]="category.id"></video-list>
これは動作し、親のCategoryComponentカテゴリが変更されるとcategoryId値が@Input()
を介して渡されますが、VideoListComponentでこれを検出し、APIServiceを介して(新しいcategoryIdを使用して)動画配列を再要求する必要があります。
AngularJSでは、変数に対して$watch
を実行したはずです。これを処理するための最良の方法は何ですか?
実際には、入力がAngular 2 +で子コンポーネントで変化したときに検出して対処する方法は2つあります。
@Input() categoryId: string;
ngOnChanges(changes: SimpleChanges) {
this.doSomething(changes.categoryId.currentValue);
// You can also use categoryId.previousValue and
// categoryId.firstChange for comparing old and new values
}
ドキュメントリンク: ngOnChanges、SimpleChanges、SimpleChange
デモの例: このplunkerを見てください
private _categoryId: string;
@Input() set categoryId(value: string) {
this._categoryId = value;
this.doSomething(this._categoryId);
}
get categoryId(): string {
return this._categoryId;
}
ドキュメンテーションリンク: ここ を見てください。
デモの例: このplunker を見てください。
どのアプローチに使用しますか?
コンポーネントに複数の入力がある場合、ngOnChanges()を使用すると、ngOnChanges()内ですべての入力に対するすべての変更を一度に取得できます。この方法を使用して、変更された入力の現在値と以前の値を比較し、それに応じてアクションを実行することもできます。
ただし、特定の1つの入力だけが変更されたときに何かをしたい場合(および他の入力を気にしない場合)は、入力プロパティ設定メソッドを使用する方が簡単かもしれません。ただし、この方法では、変更された入力の以前の値と現在の値を比較するための組み込みの方法が提供されません(これはngOnChangesライフサイクルメソッドで簡単に実行できます)。
編集2017-07-25:角度変更検出は、いくつかの回路の下でまだ消えないかもしれません
通常、setterとngOnChangesの両方の変更検出は、親コンポーネントが子に渡すデータを変更するたびに発生します。 データがJSのプリミティブデータ型(string、number、boolean) の場合。ただし、次のシナリオでは起動しません。機能させるには追加のアクションを実行する必要があります。
コンポーネントでngOnChanges()
ライフサイクルメソッドを使用してください。
ngOnChangesは、データバインドプロパティがチェックされた直後と、ビューおよびコンテンツの子がチェックされる直前に、それらのうちの少なくとも1つが変更されている場合に呼び出されます。
これが Docs です。
関数のシグネチャにSimpleChanges
型を使用すると、コンパイラとIDEの両方でコンソールにエラーが表示されました。エラーを防ぐには、代わりにシグネチャにany
キーワードを使用してください。
ngOnChanges(changes: any) {
console.log(changes.myInput.currentValue);
}
編集:
Jonが以下で指摘したように、ドット記法ではなく大括弧表記を使用するときはSimpleChanges
シグネチャを使用できます。
ngOnChanges(changes: SimpleChanges) {
console.log(changes['myInput'].currentValue);
}
最も安全な方法は@Input
パラメータのshared service代わり を使うことです。また、@Input
パラメータは複雑な入れ子になったオブジェクト型の変更を検出しません。
簡単なサービス例は次の通りです:
Service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class SyncService {
private thread_id = new Subject<number>();
thread_id$ = this.thread_id.asObservable();
set_thread_id(thread_id: number) {
this.thread_id.next(thread_id);
}
}
Component.ts
export class ConsumerComponent implements OnInit {
constructor(
public sync: SyncService
) {
this.sync.thread_id$.subscribe(thread_id => {
**Process Value Updates Here**
}
}
selectChat(thread_id: number) { <--- How to update values
this.sync.set_thread_id(thread_id);
}
}
他のコンポーネントでも同様の実装を使用でき、すべてのコンポーネントが同じ共有値を共有します。
また、親コンポーネント(CategoryComponent)の変更をトリガーするオブザーバブルを持ち、子コンポーネントのサブスクリプションでやりたいことを実行することもできます。 (videoListComponent)
service.ts
public categoryChange$ : ReplaySubject<any> = new ReplaySubject(1);
-----------------
CategoryComponent.ts
public onCategoryChange(): void {
service.categoryChange$.next();
}
-----------------
videoListComponent.ts
public ngOnInit(): void {
service.categoryChange$.subscribe(() => {
// do your logic
});
}
@Input
の値がプリミティブな値ではない場合に便利なDoCheck
というライフサイクルフックがもう1つあることを付け加えたいと思います。
私はInput
として配列を持っているので、内容が変わってもOnChanges
イベントは発生しません(Angularが行うチェックは「単純」で深くないので、配列はまだ配列であるにもかかわらず)配列の内容が変更されました。
私はそれから私が私のビューを変更された配列で更新したいかどうか決定するためにいくつかのカスタムチェックコードを実装します。
@Input()
public set categoryId(categoryId: number) {
console.log(categoryId)
}
この方法を使ってみてください。お役に立てれば
ここで、ngOnChangesはあなたの入力プロパティが変更されたときに常にトリガーします:
ngOnChanges(changes: SimpleChanges): void {
console.log(changes.categoryId.currentValue)
}
NgOnChangeを実装したり、onChange()メソッドを実装したくない場合は、 valueChangesイベント 、ETCで特定の項目の変更を購読することもできます。
myForm= new FormGroup({
first: new FormControl()
;));
this.myForm.valueChanges.subscribe(formValue => {
this.changeDetector.markForCheck();
});
この宣言で使用するために書かれたmarkForCheck()
changeDetection: ChangeDetectionStrategy.OnPush