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

    ×