@ViewChild を用いたコンポーネント

Angular では、あるコンポーネントを含む親コンポーネントを作成することで、コンポーネントの機能を拡張することが可能です。

オブジェクト指向プログラミングでは、クラス A がクラス B を含む関係をコンポジションといいます。クラス A がクラス B を持っている、ということで、has-a の関係などと言ったりしますが、 Angular ではこうした has-a 関係をコンポーネントの単位でサポートしています。

子コンポーネントを取り込むために @ViewChild 修飾子を使います。

さっそく具体例を紹介します。

まず CountComponent (src/app/count.component.ts) を次のように定義します。

import {Component, Input} from '@angular/core';

@Component({
  selector: 'count',
  template: `<span>{{c}}</span>`
})
export class CountComponent {
  @Input() c: number;

  inc(){
    this.c++;
  }
}

number 型のプロパティとして c があります。テンプレートは c を表示しているだけです。

@Input 修飾子はテンプレートからコンポーネントを初期化するために使います。「入力プロパティ」をみてください。

また、inc というメソッドがあり、このメソッドを呼べば c をインクリメント (1 足す) します。

次に、この CountComponent を含む (使う) コンポーネントを作成します。AppComponent を次のように書き換えます。

import { Component, ViewChild } from '@angular/core';
import { CountComponent } from './count.component';


@Component({
  selector: 'app-root',
  template: `
  <div>
    <count [c]="100"></count>
    <button (click)="onClick()">+</button>
  </div>
  `
})
export class AppComponent {
  @ViewChild(CountComponent)
  private countComponent: CountComponent;

  onClick(){
    this.countComponent.inc();
  }
}

@ViewChild 修飾子で CountComponent 型のプロパティ countComponent を宣言しています。 これは自動的にテンプレート内に出現する CountComponent 要素 (セレクタ count) に関連付けされます。

実行すると次のようになります。

ボタンを押すと、click イベントのハンドラにて CountComponent オブジェクトの inc メソッドを呼び出すことで、 カウンターの数字がインクリメントされます。

このように、CountComponent は c を表示するだけのコンポーネントでしたが、AppComponent でボタンを設置し実行時に値を変更することができました。

複数の子コンポーネントを含む場合

複数の同じ子コンポーネントを含む場合は、テンプレート参照変数を用いてプロパティとテンプレート内の要素を明示的に関連付けします

コードは次のようになります。

import { Component, ViewChild } from '@angular/core';
import { CountComponent } from './count.component';

@Component({
  selector: 'app-root',
  template: `
  <div>
    <count #v1 [c]="100"></count>
    <button (click)="onClick1()">+</button>
  </div>
  <div>
    <count #v2 [c]="1"></count>
    <button (click)="onClick2()">+</button>
  </div>
  `
})
export class AppComponent {
  @ViewChild('v1')
  private countComponent: CountComponent;

  @ViewChild('v2')
  private countComponent2: CountComponent;

  onClick1(){
    this.countComponent.inc();
  }

  onClick2(){
    this.countComponent2.inc();
  }

}

以上で、@ChildView 修飾子を用いたコンポーネントのコンポジット集約方法について説明しました。