2017-11-26 20 views
0

子コンポーネントを完全に再読み込みできる必要があります。これを実現する最善の方法は、単純な*ngIfをブール値で使用することです。子コンポーネントの破棄と再ロード

<app-child *ngIf="enabled"></app-child> 

しかし、それだけでこれを行うことはすぐに再初期化/コンポーネントを削除するには十分ではないようです。つまり、コンポーネントを削除するにはfalseを設定し、それを再初期化するには、trueに設定されむしろ

reloadTree(){ 
    this.enabled = false; 
    this.enabled = true; // doesn't work- child ngOnInit isn't called 
} 

、私はそれが動作する前にsetTimeoutを使用する必要があります。

reloadTree(){ 
    this.enabled = false; 
    const self = this; 
    setTimeout(function(){ 
    self.enabled = true; 
    }, 1); 
} 

私は、これは角度がテンプレートをレンダリングする方法で行うことですね?これは非常に優雅ではない - 誰も私がここでやろうとしていることを達成するためのより良い方法を提案することができますか?ありがとう

+0

なぜ最初にリロードする必要がありますか?それは設計上の問題のようです。代わりに、おそらくそれを別の入力に渡すか、または観測対象から放出されたイベントに反応させるべきです。 –

+1

フラグ切り替えの間に角度変化検出を積極的に行う必要があるかもしれません。この[ChangeDetectionRef](https://angular.io/api/core/ChangeDetectorRef)はここで役立ちます。それを挿入し、 'this.ref.detectChanges'を呼び出します。 –

+0

私はそれが少しハックだと認めます。ここに入る価値はありませんが、私は特定の問題を抱えている日々を過ごしましたが、これを回避する唯一の方法と思われます。 @ BenediktSchmidt-ありがとう、あなたは精巧にできますか? – Inigo

答えて

1

これはレコードのためだけであり、それを行うためのきれいな方法であるかどうかを主張することなく、フラグトグルで問題を回避する方法は次のとおりです。主なアイデアは、子コンポーネントを破棄して後で再作成することです。これは子コンポーネントの単純な* ngIfフラグで行うことができます。

フラグがの場合、に切り替えると、子コンポーネントは破棄され、DOMから完全に削除されます。その後、に再度設定して新しいインスタンスを作成することができます(私がここで間違っていない場合)。

特定のコードの問題と、setTimeoutメソッドの回避策の必要性は、角度がそれらに反応するための変更を認識する必要があることです。この場合、2行のコード内での切り替えは、角度を変更するのが速すぎるかもしれません(あるいは、コンパイラによっても最初の行が削除されることもありますので、変更されることはありません)。コンポーネントが削除されず、新しいインスタンスが作成されません。

reloadTree(){ 
    this.enabled = false; // switching to false 
    this.enabled = true; // and back to true 
    // this does not notify angular that something has actually changed 
} 

私たちが行う必要があるのは、値が変更されたことを手動で角度に伝えることです。これは、コンポーネントに注入できる角度ChangeDetectionRefクラスで行うことができます。 enabledフラグの切り替えの間に、変更を検出するためにangleを通知するので、コンポーネントを完全に削除することで応答することができます。次に、それをtrueに戻して新しいインスタンスを作成することができます。

constructor(private changeDetector: ChangeDetectorRef){} 

reloadTree(){ 
    this.enabled = false; 
    // now notify angular to check for updates 
    this.changeDetector.detectChanges(); 
    // change detection should remove the component now 
    // then we can enable it again to create a new instance 
    this.enabled = true; 
} 
+1

素晴らしいこと、これはうまく仕事をします。ありがとう。 – Inigo

0

なぜコンポーネントを破壊しているのですか?これは間違ったやり方です。サービスにリロードする必要があるデータを入れ、RxJS SubscriberまたはEventEmitterを介して何かが変更されたことを通知します。更新イベントは、サービスをコンストラクタに注入してトリガメソッドを呼び出すことによって、他のコンポーネントによってトリガされます。

+0

私は、あなたが提案したすべてをやろうとしましたが、いろいろな理由でうまくいきません。これはネストされたリストを持つ剣道UIソート可能なプラグインに関係します。新しいデータを認識させる方法を考えることができません。おそらく私は彼らの方法を理解していないか、ドキュメンテーションが不足していますが、私はもうこれ以上時間を無駄にすることはできません。必要ならば 'setTimeout'をつけておきます... – Inigo

+0

あなたの問題はZone.jsだと思います。何かがngZoneの外側で実行されている場合、変更検出がトリガされないため、Angularはデータを更新しません。ゾーンが完了するとゾーン内で実行されます。oneEventDoneが呼び出され、angleがcha​​ngeDetectionを開始しますあなたが角度の世界で作業しているときに、いくつかの外部のものを使うときは、それを起動するか、新しいカスタムngZone(zone.run(()=> {..}))で実行する必要があります。 ) –

関連する問題