Angularで手動で変更検出をトリガーする


387

プロパティを持つAngularコンポーネントを書いていますMode(): string

イベントに応答せずに、このプロパティをプログラムで設定できるようにしたいと思います。

問題は、ブラウザーイベント{{Mode}}がない場合、テンプレートバインディングが更新されないことです。

この変更検出を手動でトリガーする方法はありますか?

回答:


640

次のいずれかを試してください。

  • ApplicationRef.tick()-AngularJSと同様$rootScope.$digest()-コンポーネントツリー全体をチェック
  • NgZone.run(callback)-に似ています$rootScope.$apply(callback)-つまり、Angularゾーン内のコールバック関数を評価します。コールバック関数を実行した後、コンポーネントツリー全体をチェックすることになると思いますが、よくわかりません。
  • ChangeDetectorRef.detectChanges()-に似ています$scope.$digest()-つまり、このコンポーネントとその子のみをチェックします

あなたは、注入することができApplicationRefNgZoneまたはChangeDetectorRefあなたのコンポーネントに。


1
おかげで、変更はかなりローカライズされているため、すべてをチェックしないように3番目のソリューションを選択しました。時間があれば、他のオプションを調査する必要があります。それぞれの選択でパフォーマンスへの影響はありますか?
jz87

36
の+1 ChangeDetectorRef.detectChanges()。ディレクティブが入力の値を更新する前にバリデーターが発動していました。
ps2goat

7
ApplicationRef.tick()とChangeDetectorRef.detectChanges()は、2.0.0 finalにも存在します。
Max Mumford

51
私はこれについて言及すると思いました。これらは静的メソッドではなく、インスタンスメソッドです。これらのクラスをサービスとして注入する必要があります。
スティーブンポール

1
ApplicationRef.tick()は、FireFox v17(<20)の問題を解決するのに役立ちました
Dan J

123

私は受け入れられた回答リファレンスを使用して例を挙げたいと思います。Angular2のドキュメントは非常に読みにくいので、これが簡単であることを願っています。

  1. インポートNgZone

    import { Component, NgZone } from '@angular/core';
    
  2. クラスコンストラクターに追加します。

    constructor(public zone: NgZone, ...args){}
    
  3. でコードを実行zone.run

    this.zone.run(() => this.donations = donations)
    

6
あなたはどこにzone.runコードを置くべきですdonationsか、そして正確には何ですか?
スク

@suku donationsは更新したいプロパティなので、this.foo = barのようになります。zone.runは、更新したい場所に移動します。
Matthew Optional Meehan

4
document.addEventListener( "resume"、callback)を使用するときに、このソリューションを使用してビューを強制的に更新しました
marcovtwout

71

markForCheck()で更新できました

ChangeDetectorRefのインポート

import { ChangeDetectorRef } from '@angular/core';

注入してインスタンス化する

constructor(private ref: ChangeDetectorRef) { 
}

最後に、変更検出を実行するようにマークします

this.ref.markForCheck();

markForCheck()が機能し、detectChanges()が機能しない例を次に示します。

https://plnkr.co/edit/RfJwHqEVJcMU9ku9XNE7?p=preview

編集:この例では、問題はもう描かれていません:(修正された新しいAngularバージョンが実行されている可能性があります。

(STOP / RUNを押して再度実行します)


detectChanges()のGooポイントが機能していません。私は同じ問題に気づき、変更の検出がOnPushでない場合に機能することを発見しました。それについての説明を得るのは良いことでしょう...
クリスチャン

2
detectChangesが実際にこのプランカーで機能しているようです?何か不足していますか?
Jared_C 2017

1
ChangeDetectorRefはコンポーネントでのみ機能することに注意してください
kevinius

(!)これは悪い例です、申し訳ありません。例は何も示していません。最初のアイテムは上書きされます。タイマーを少し調整するだけ
Peter Stegnar

この例では、もはや問題を描いていない:(私はそれはそれは固定だ新しい角度のバージョンを実行しているかもしれないと考えている。
ヌーノ・トーマス

7

Angular 2+では、@ Inputデコレーターを試してください

これにより、親コンポーネントと子コンポーネントの間の適切なプロパティバインディングが可能になります。

最初に、親にグローバル変数を作成して、子に渡されるオブジェクト/プロパティを保持します。

次に、親から渡されたオブジェクト/プロパティを保持するために子にグローバル変数を作成します。

次に、子テンプレートが使用される親HTMLで、角括弧表記を子変数の名前で追加し、親変数の名前と同じに設定します。例:

<child-component-template [childVariable] = parentVariable>
</child-component-template>

最後に、子コンポーネントで子プロパティが定義されている場所に、Inputデコレータを追加します。

@Input()
public childVariable: any

親変数が更新されると、子コンポーネントに更新が渡され、HTMLが更新されます。

また、子コンポーネントで関数をトリガーするには、ngOnChangesをご覧ください。


2
いいえ...それは問題です...親で更新した場合...たとえば、静的メソッドで「参照」によって更新された場合、変更の検出が発生しなかったため、子はそれを取得しません
Bhail

私は何日も同じ問題を抱えています。PHPバックエンドからデータを取得しようとすると、データがまったく更新されません。Microsoft Edgeでは正常に機能しますが、他のブラウザでは機能しません。最初に取得したデータを取得し続けますが、データが変更されてもビューで更新されません
el6976

1

ChangeDetectorRef.detectChanges()-$ scope。$ digest()と同様-つまり、このコンポーネントとその子のみをチェックします

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.