2016-02-24 8 views
17

かなり大きなAngular 1.xアプリケーションがあるので、Angular 2に完全にアップグレードすることはできませんが、私は新しいアーキテクチャが好きです。バージョン1.5は、同じ古いアプリに素晴らしいcomponentをもたらします。すべてのクールなものとして、それはドキュメントが欠けています;-)角度1.5のonChangesが機能しない

ここに質問があります。コントローラの定義には、次の2つの行があります。

this.$onInit = setType; 
this.$onChanges = setType; 

第1は動作していますが、第2は動作していません。私は'<'バインディングを使用しています。したがって、最初のロードでは、コンポーネントの状態は渡された値に従って設定され、変更は反映されません。私はそれが[1]と[2]からうまくいくはずです。

[1] https://docs.angularjs.org/guide/component

を[2] https://angular.io/docs/js/latest/api/core/OnChanges-interface.html

UPDは [OK]を、私は動作するようになっていないことを学んだ: https://github.com/angular/angular.js/issues/14030

誰もが良いの回避策を知っていますか?

UPD2それは私の知る限り1.5.3

+0

クイックフィードバック:子コンポーネントで '$ onChange()'をトリガする値を変更するとき、オブジェクト(プリミティブではない)で 'angular.copy()'を実行する必要がありました。 – Maxence

+0

この$ doCheckを試してくださいhttp://www.kristofdegrave.be/2016/07/component-lifecycle-docheck-angular-15x_22.html –

答えて

7

のように動作し、両方$onChanges$onInit方法はAngularJSバージョン1.5.3で動作するはずです。

私はplnkr that demonstrates both usagesを作成しました。

これは、一方向バインディング演算子<を使用して外側と内側の2つのコンポーネントを持ちます。入力フィールドは、外部コンポーネントの値を更新します。入力フィールドにキーボードを入力するたびに、メソッドが起動されます(コンソールを開いて表示します)。 AngularJs 1.5.3のよう

angular.module("app", []) 
.component("outer", { 
    restrict: "E", 
    template: `<input ng-model=$ctrl.value> <br /> 
      <inner value="$ctrl.value"> 
      </inner>` 
}) 
.component("inner", { 
    restrict: "E", 
    template: `{{$ctrl.value}}`, 
    bindings: { 
     value: "<" 
    }, 
    controller: function(){ 
     function setType() { 
      console.log("called"); 
     } 
     this.$onInit = setType; 
     this.$onChanges = setType; 
    } 
}); 
+0

1.5.3はまだリリースされていませんが、それはありますか?私は1.5.0を指していましたが、最初の質問を書いた時点で1.5.xブランチの唯一のものでした。 – leitasat

+0

とにかく知っておいてよかった、ありがとう! – leitasat

+2

1.5.3は約1週間前にリリースされました。フックはそのバージョンで導入されました:) – KwintenP

17

、ctrl.someModelは、子コンポーネントに一方向にバインドされている想定し、以下は$ onChangesをトリガしません。

function get() { 
    api.getData().then((data) => { 
    ctrl.someModel.data = data 
    } 
} 

オブジェクトの更新プロパティが更新プログラムとして認識されないようです。

これは私が現在それを回避する方法です。私はそれが最良の解決策であるとは思わないが、$ onChangesを引き起こす。私は初期モデルの深いコピーを作成し、そのデータをそのプロパティの1つとして追加してから、新しいオブジェクトの値に初期モデルを設定します。

function get() { 
    api.getData().then((data='42') => { 
    const updatedModel = angular.copy(ctrl.someModel) 
    updatedModel.data = data 
    ctrl.someModel = updatedModel 
    } 
} 

子成分(「データ」としてバインドされたようにモデルを仮定)で:

this.$onInit = function(bindings) { 
    if (bindings.data && bindings.data.currentValue) { 
    console.log(bindings.data.currentValue) // '42' 
    } 
} 
+0

これは、本質的に不変のデータを使用しているので、実際には良い解決策です。したがって、フラックスとこのすべてのもので完璧に動作します。 – leitasat

+2

これはこれを修正する良い方法です。しかし、それはより良いことができます。私はImmutableJSを使用して、これを「よりクリーンな」方法で修正する方法の例をブログに書いています。 http://blog.kwintenp.com/the-onchanges-lifecycle-hook/ – KwintenP

+1

私は同様の問題がありましたが、コピーの代わりに配列を扱っていたので、コピーを返す 'Array.slice()'を使用しました。配列の '$ onChanges'は実際にコンポーネントで起動されます。ありがとう! – Nobita

9

ディーリング本質的に、私は、ライフサイクルフックによってピックアップされたオブジェクト全体を更新します$onChangesの場合は扱いにくいです。実際、バージョン1.5.8ではAngular 2 ngDoCheckと同様に$doCheckが導入されました。

この方法では、手動で内のオブジェクトが聞かれて変化を聞くことができ、これは、(オブジェクトの参照が変更された場合にのみ呼び出される)$onChangesフックでは発生しませありません。同じことですが、ダイジェストサイクルごとにが呼び出されて、手動で変更を確認できます(ただし、時計は良くなります)。詳細については

this blog post

0

基本的には、$ onChanges角度ライフサイクルフック・トリガー時に順番に子で$ onChangesを起動するので、参照の変更(変更されたオブジェクトではないプロパティ)の角度を見つけるを参照してください親では、新しいオブジェクトを割り当てます。あなたが本当にすべてのダイジェストサイクルのコールバックをトリガする場合を除き、それは関係なく、いくつかの結合の変化か、すべての$ダイジェストサイクルで呼び出されていないので、例えば、

angular.module("app", []) 
.component("outer", { 
    restrict: "E", 
    controller : function(){ 
     this.value = {}; 
     this.userButtonClick = function(someValue){ 
      this.value = angular.copy(someValue); 
     } 
    }, 
    template: `<input ng-click="$ctrl.userButtonClick({somevalue : "value"})" /> 
    <br /> 
      <inner value="$ctrl.value"> 
      </inner>` 
    })   
.component("inner", { 
     restrict: "E", 
     template: `{{$ctrl.value}}`, 
     bindings: { 
      value: "<" 
     }, 
     controller: function(){ 
      function setType() { 
       console.log("called"); 
      } 
      this.$onInit = setType; 
      this.$onChanges = function(changeObj){ 
       console.log("changed value",changeObj.value.currentValue); 
      } 
     } 
    }); 

は、doCheck $を使用しないでください。

関連する問題