Angularの公式ドキュメントでは解説されていない、@ViewChildと@ContentChildの秘密

2024-04-02

Angularにおける@ViewChildと@ContentChildの違い

@ViewChildは、コンポーネントテンプレート内の要素を取得するために使用されます。 一方、@ContentChildは、別のコンポーネントから直接要素を取得するために使用されます。

それぞれの特徴

項目@ViewChild@ContentChild
取得対象テンプレート内の要素別のコンポーネント
適用対象コンポーネントコンポーネント
取得方法参照名プロパティ
使用例子コンポーネントへのアクセスプロジェクションされたコンテンツへのアクセス

  • @ViewChild
<button #myButton (click)="onClick()">Click me!</button>
@Component({
  selector: 'my-component',
  templateUrl: './my-component.html',
})
export class MyComponent {
  @ViewChild('myButton') button!: ElementRef;

  onClick() {
    this.button.nativeElement.click();
  }
}
  • @ContentChild
<my-child>
  <p>This is projected content</p>
</my-child>
@Component({
  selector: 'my-parent',
  templateUrl: './my-parent.html',
})
export class MyParentComponent {
  @ContentChild(MyChildComponent) child!: MyChildComponent;
}

@Component({
  selector: 'my-child',
  templateUrl: './my-child.html',
})
export class MyChildComponent {
  // ...
}
  • @ViewChildは、テンプレート内の要素を取得する
  • @ContentChildは、別のコンポーネントから直接要素を取得する

どちらを使用するかは、取得したい要素の場所によって異なります。




@ViewChild

<div>
  <button #myButton (click)="onClick()">Click me!</button>
</div>
@Component({
  selector: 'my-parent',
  templateUrl: './my-parent.html',
})
export class MyParentComponent {
  @ViewChild('myButton') button!: ElementRef;

  onClick() {
    console.log('Button clicked!');
  }
}

@ContentChild

子コンポーネント

<p>This is projected content</p>
@Component({
  selector: 'my-child',
  templateUrl: './my-child.html',
})
export class MyChildComponent {
  // ...
}
<my-parent>
  <my-child>
    <p>This is projected content</p>
  </my-child>
</my-parent>
@Component({
  selector: 'my-parent',
  templateUrl: './my-parent.html',
})
export class MyParentComponent {
  @ContentChild(MyChildComponent) child!: MyChildComponent;

  constructor() {
    console.log('Child component:', this.child);
  }
}

実行結果

Child component: MyChildComponent {
  // ...
}

Button clicked!

my-parent.htmlテンプレート内の#myButtonという参照名のボタン要素を取得し、MyParentComponentクラスのbuttonプロパティに格納しています。 onClick()メソッド内で、buttonプロパティのnativeElementプロパティを使用して、ボタン要素のclick()イベントを発火しています。

my-parent.htmlテンプレート内でmy-childコンポーネントがプロジェクションされた内容を取得し、MyParentComponentクラスのchildプロパティに格納しています。 constructor内で、childプロパティの内容を出力しています。




Angularで要素を取得する他の方法

テンプレート変数を使用して、テンプレート内の要素に直接アクセスできます。

<button #myButton (click)="onClick()">Click me!</button>
@Component({
  selector: 'my-component',
  templateUrl: './my-component.html',
})
export class MyComponent {
  onClick() {
    console.log('Button clicked:', myButton);
  }
}

ElementRefを使用して、DOM要素への直接アクセスを取得できます。

<button (click)="onClick($event)">Click me!</button>
@Component({
  selector: 'my-component',
  templateUrl: './my-component.html',
})
export class MyComponent {
  onClick(event: Event) {
    const button = event.target as HTMLButtonElement;
    console.log('Button clicked:', button);
  }
}

QueryListを使用して、特定の条件に一致する要素のリストを取得できます。

<div>
  <button #button1>Button 1</button>
  <button #button2>Button 2</button>
</div>
@Component({
  selector: 'my-component',
  templateUrl: './my-component.html',
})
export class MyComponent {
  @ViewChildren('button') buttons!: QueryList<ElementRef>;

  ngAfterViewInit() {
    console.log('Buttons:', this.buttons);
  }
}

getElementsByClassName()を使用して、特定のクラス名を持つ要素のリストを取得できます。

<div>
  <button class="my-button">Button 1</button>
  <button class="my-button">Button 2</button>
</div>
@Component({
  selector: 'my-component',
  templateUrl: './my-component.html',
})
export class MyComponent {
  ngAfterViewInit() {
    const buttons = document.getElementsByClassName('my-button');
    console.log('Buttons:', buttons);
  }
}
  • テンプレート変数は、最もシンプルで簡単な方法です。
  • @ViewChildは、コンポーネントテンプレート内の特定の要素を取得する必要がある場合に適しています。
  • QueryListは、特定の条件に一致する要素のリストを取得する必要がある場合に適しています。

angular


【Angular】コンポーネントのセレクタータグを変更して、コードをもっとスマートに

本記事では、Angular コンポーネントのセレクタータグを削除または置換する方法について、分かりやすく日本語で解説します。セレクタータグを削除する方法は、以下の 2 つがあります。コンポーネントクラスの @Component デコレータには、selector プロパティが定義されています。このプロパティには、コンポーネントを呼び出す際に使用されるセレクタータグを指定します。...


AngularでtoLocaleDateString()メソッドを使って日付をdd/MM/yyyy形式で表示する

Angular CLIDatePipeAngular CLIを使って新しいプロジェクトを作成します。app. module. tsファイルにDatePipeをインポートします。app. component. htmlファイルで、DatePipeを使って日付をフォーマットします。...


Angular 2 フォーム送信がキャンセルされる?原因と解決策をわかりやすく解説

原因: フォーム送信がキャンセルされる理由はいくつかあります。preventDefault() メソッド: フォーム送信イベントの preventDefault() メソッドを呼び出すと、送信がキャンセルされます。form. reset() メソッド: form...


【保存版】Angular、TypeScript、RxJSで発生するrxjs/Subject.d.tsエラー:原因、対策、回避策を完全網羅

このエラーは、TypeScript 2.4 以降で RxJS 5.5 以前を使用している場合に発生します。RxJS 5.5 以降では、Subject クラスの lift プロパティの型が変更されましたが、rxjs/Subject. d.ts ファイルの型定義は古いままになっています。そのため、TypeScript コンパイラは、Subject クラスが Observable クラスを誤って拡張しているというエラーを出力します。...


Angular FormGroupにFormControlを動的に追加:完全ガイド

まず、以下のライブラリをインポートする必要があります。FormArray を使用すると、動的に FormGroup を追加することができます。FormArray インスタンスを作成します。push() メソッドを使用して、FormGroup インスタンスを FormArray に追加します。...