Jump to the content

必ず覚えておきたい! Angular2でコンポーネントの子要素を参照する方法

Angular2

必ず覚えておきたい! Angular2でコンポーネントの子要素を参照する方法

Angular2でアプリケーションを構築する時に、 親コンポーネントから子コンポーネントを操作したいことが多くあります。 例えば、子コンポーネントの値を取得・変更したい時や、DOMを取得したい時などが挙げられます。

Angular2では、ViewChildrenContentChildren を使用することで、 親要素から子要素を参照することができます。

今回はViewChildrenContentChildren を使用した、子要素の参照方法を紹介します。

ViewChildren とは

コンポーネントのテンプレートの中に配置された子要素ViewChildren と呼びます。

使い方は、@ViewChildren もしくは @ViewChild デコレータを @angular/core からインポートして使用します。
@ViewChildren は複数個取得でき、@ViewChild は1つだけ取得するという違いがあります。

次のコードでは、@ViewChildren を使用して子要素を参照しています。

parent.ts
import { Component, ViewChildren } from '@angular/core'
import { ChildComponent } from './child';

@Component({
  selector: 'my-parent',
  providers: [],
  template: `
    <div>children count: <strong>{{ count }}</strong></div>
    <div>
      <ol>
        <my-child *ngFor="let log of logs" [log]="log"></my-child>
      </ol>
    </div>
  `,
  directives: [
    ChildComponent
  ]
})
export class ParentComponent implements AfterViewInit {

  logs = [ 'foo', 'bar', 'baz' ];
  count = 0;

  @ViewChildren(ChildComponent) children: QueryList<ChildComponent>;

  // 子コンポーネントの初期化後に実行
  ngAfterViewInit() {
    this.count = this.children.length;
  }

}

次のコードがデコレータの使用部分です。

@ViewChildren(ChildComponent) children: QueryList<ChildComponent>;

@ViewChildren() の引数に、ChildComponent を渡すことで、自身のテンプレート内の ChildComponent を取得するよう指定します。
取得結果としての返り値は QueryList と呼ばれる、配列に似た要素集合で取得するのが一般的です。QueryListは、forEach メソッドでの繰り返し処理や、 length プロパティによる要素数の取得が可能です。

this.count = this.children.length;

デモでは ChildComponent の数を出力しています。

ContentChildren とは

開始タグと終了タグの間に置かれた要素ContentChildren と呼びます。

使い方は、ViewChildrenと同じく、@ContentChildren@ContentChild デコレータを @angular/core からインポートして使用します。
こちらも、@ContentChildren は複数個取得でき、@ContentChild は1つだけ取得するという違いがあります。

次のコードでは、@ContentChildren を使用して子要素を参照しています。

parent.ts
import { Component, ContentChildren, QueryList, AfterContentInit } from '@angular/core'

// Name
@Component({
  selector: 'my-name',
  template: `<li><ng-content></ng-content></li>`
})
class NameComponent {}

// Child
@Component({
  selector: 'my-child',
  template: `
    <div>children count: <strong>{{ count }}</strong></div>
    <ng-content></ng-content>
  `
})
class ChildComponent implements AfterContentInit {

  count = 0;
  @ContentChildren(NameComponent) children: QueryList<NameComponent>;

  // 子要素の初期化後に実行
  ngAfterContentInit() {
    this.count = this.children.length;
  }
}

// Parent
@Component({
  selector: 'my-parent',
  template: `
    <my-child>
      <ol>
        <my-name *ngFor="let name of members">{{ name }}</my-name>
      </ol>
    </my-child>
  `,
  directives: [
    ChildComponent,
    NameComponent
  ]
})
export class ParentComponent implements AfterContentInit, AfterViewInit {

  members = [ 'のび太', 'スネ夫', 'ジャイアン', '出木杉' ];

}

ParentComponent のテンプレート部分に注目してください。

template: `
  <my-child>
    <ol>
      <my-name *ngFor="let name of members">{{ name }}</my-name>
    </ol>
  </my-child>
`,

ChildComponent の要素の中にolリストが含まれています。 このolリストが ChildComponentContentChild となります。

デモでは ChildComponent の中にある、NameComponent の数を出力しています。

まとめ

今回紹介した内容は、コンポーネント・要素を参照するための基本になりますので、しっかり抑えておきたいです。

このViewやContentという考え方は、Lifecycle Hooks でも応用が効き、 Angular2でのアプリケーション構築では欠かすことのできない重要な概念です。 あわせて Lifecycle Hooks の記事を読むとより一層理解が深まるでしょう。

参考

注目記事

最近の記事

プロフィール

イソップ

ページの先頭に戻る

Search results

×