概要

親コンポーネントのデータを子コンポーネントに渡して、その値を子コンポーネントで利用出来ますが、今回そのデータ自体が親コンポーネントで更新された際の動作を監視する方法を調べたのでメモします。

コード

子コンポーネント

子コンポーネントは以下のとおりです。

class ChildComponent implements AfterChanges {

  @Input()
  List<String> something;
  @override
  void ngAfterChanges() {
    print('なんかsomethingの値が更新されたよ!');
  }
}

親コンポーネント

で、親側のparent_component.htmlは以下のような内容

<child [something]="somethingByParent"></child>
<button (click)="test()">test</button>

親側のparent_component.dartは以下。

class ParentComponent implements OnActivate {
List<String> somethingByParent;
  @override
  void onActivate(_, RouterState current) async {
    somethingByParent = ['a', 'b'];
  }
  void test() {
    // List.fromは、型宣言を省略すると戻り値の型がList<dynamic>になってしまうので、
    // ちゃんと型付きの変数宣言をしてあげる必要が有る。
    final List<String>tmp = List.from(somethingByParent)..add('c');
    somethingByParent = tmp;
  }
}

これで、testボタンをクリックすれば、親コンポーネントのtest()が実行されて、somethingByParentの中身を新しい値で上書きします。
そうするとその度に、@InputでそのsomethingByParentのデータを参照している子コンポーネント側では、somethingsomethingByParentの値が入ってきた後に、自動的にngAfterChangesが実行されます。

なお、AngularDartでは、オブジェクトの内容の更新までは自動で検知(今回のAfterChanges等)はしてくれないようで、変数の中身自体を上書きしてあげる必要が有ります。

以下は、正しく子コンポーネント側でAfterChangesなどの変更検知イベントが動かない例です。

// NG1
// 変数を上書きせずにオブジェクトの内容のみ変更している為NG
somethingByParent.add('c');

// NG2
// Dartの制限なのかよく分かっていないが、以下の例だと実質somethingByParentオブジェクトである事自体には変わりが無いため、
// 結果的に子コンポーネントでAfterChangesは呼ばれない。
final List<String>tmp = somethingByParent;
tmp.add('c');
somethingByParent = tmp;

感想

Angular自体初めてなので、完璧に五里霧中です。
ただ、今回コンポーネント間でデータをやり取りする処理を書いてみて、型が無いとコレは無茶苦茶大変だな、という事は容易に想像できたので、やはりAngularDart自体はナイスな選択肢だなと言う思いが強くなりました。

参考

Lifecycle Hooks
PREFER implementing AfterChanges to OnChanges