Dev Study
← Angular コース

63. contentChild() — 差し込まれた中身をクラスから掴む

viewChild() のレッスンでは、自分のテンプレートに書いた要素をクラスから取得しました。一方、ng-content のレッスンで学んだように、コンポーネントには親から「タグの間に差し込まれた中身」もやってきます。この差し込まれた中身は自分のテンプレートに書いたものではないので、viewChild() では取れません。そこで使うのが contentChild() と contentChildren() です。

view と content の区別を整理しておきましょう。自分の template に自分で書いたものが view、利用側が <app-tabs>...</app-tabs> のようにタグの間へ差し込んだものが content です。contentChild(TabPanelComponent) のように取りたいコンポーネントの型(またはテンプレート参照変数の名前)を指定すると、差し込まれた中からそれを探して、シグナルとして返してくれます。複数まとめて取りたいときは contentChildren() です。

この道具が活躍するのは、タブやアコーディオンのように「利用側が並べた子部品を、親が束ねて制御する」コンポーネントを作るときです。親は contentChildren() で差し込まれたパネルの一覧をシグナルで受け取り、computed でタブボタンの一覧を作る、といった具合に、これまで学んだシグナルの道具とそのまま組み合わせられます。

サンプルコード(フレームワーク環境が必要なため表示のみ)

import { Component, contentChildren, computed } from '@angular/core';
import { TabPanelComponent } from './tab-panel.component';

@Component({
  selector: 'app-tabs',
  // 利用側: <app-tabs><app-tab-panel title="基本"/>...</app-tabs>
  template:
    '@for (title of titles(); track title) {' +
    '  <button>{{ title }}</button>' +
    '}' +
    '<ng-content />',
})
export class TabsComponent {
  // タグの間に差し込まれた TabPanelComponent を全部集める
  panels = contentChildren(TabPanelComponent);

  // シグナルなので computed とそのまま組み合わせられる
  titles = computed(() => this.panels().map((p) => p.title()));
}
サンプルコードで身につける(5本) →

学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。

公式ドキュメントで詳しく ↗