序章

この記事では、AngularのViewChildデコレータを紹介します。

親コンポーネントクラスからディレクティブ、子コンポーネント、またはDOM要素にアクセスしたい場合があります。 ViewChildデコレータは、指定されたディレクティブ、コンポーネント、またはテンプレート参照セレクターに一致する最初の要素を返します。

前提条件

このチュートリアルを実行したい場合:

  • @ angle /cliのインストールを検討してください。
  • @angular/cliを使用して、でViewChild機能をテストするための新しいプロジェクトを作成します。

このチュートリアルは、@angular/corev13.0.2および@angular/cliv13.0.3で検証されました。

ディレクティブでのViewChildの使用

ViewChildを使用すると、ディレクティブにアクセスできます。

SharkDirectiveがあるとします。 このディレクティブは、属性appSharkを持つ要素を検索し、要素内のテキストの前に"Shark"という単語を追加します。

理想的には、@angular/cliからgenerateのディレクティブを使用します。

  1. ng generate directive shark --skip-tests

このコマンドは、shark.directive.tsファイルを作成します。 そして、ディレクティブをapp.module.tsに追加します。

app.module.ts
import { SharkDirective } from './shark.directive';
...
@NgModule({
  declarations: [
    AppComponent,
    SharkDirective
  ],
  ...
})

次に、ElementRefRenderer2を使用してテキストを書き直します。 shark.directive.tsの内容を次のように置き換えます。

shark.directive.ts
import {
  Directive,
  ElementRef,
  Renderer2
} from '@angular/core';

@Directive(
  { selector: '[appShark]' }
)
export class SharkDirective {
  creature = 'Dolphin';

  constructor(elem: ElementRef, renderer: Renderer2) {
    let shark = renderer.createText('Shark ');
    renderer.appendChild(elem.nativeElement, shark);
  }
}

次に、コンポーネントテンプレートのテキストを含むspanappShark属性を追加します。 app.component.htmlの内容を次のように置き換えます。

app.component.html
<span appShark>Fin!</span>

ブラウザでアプリケーションを表示すると、要素のコンテンツの前に"Shark"という単語が表示されます。

Output
Shark Fin!

これで、SharkDirectivecreatureインスタンス変数にアクセスし、その値でextraCreatureインスタンス変数を設定することもできます。 app.component.tsの内容を次のように置き換えます。

app.component.ts
import {
  Component,
  ViewChild,
  AfterViewInit
} from '@angular/core';
import { SharkDirective } from './shark.directive';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
  extraCreature!: string;

  @ViewChild(SharkDirective)
  set appShark(directive: SharkDirective) {
    this.extraCreature = directive.creature;
  };

  ngAfterViewInit() {
    console.log(this.extraCreature); // Dolphin
  }
}

このコードは、セッターを使用してextraCreature変数を設定しました。 AfterViewInit ライフサイクルフックが変数にアクセスするのを待機していることに注意してください。これは、子コンポーネントとディレクティブが使用可能になったときです。

ブラウザでアプリケーションを表示すると、"Shark Fin!"メッセージが表示されます。 ただし、コンソールログには次のように表示されます。

Output
Dolphin

親コンポーネントは、ディレクティブから値にアクセスできました。

DOM要素でのViewChildの使用

ViewChildを使用すると、テンプレート参照変数を持つネイティブDOM要素にアクセスできます。

テンプレートに#someInput参照変数を持つ<input>があるとします。 app.component.htmlの内容を次のように置き換えます。

app.component.html
<input #someInput placeholder="Your favorite sea creature">

これで、ViewChild<input>にアクセスし、valueを設定できます。 app.component.tsの内容を次のように置き換えます。

app.component.ts
import {
  Component,
  ViewChild,
  AfterViewInit,
  ElementRef
} from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
  @ViewChild('someInput') someInput!: ElementRef;
  ngAfterViewInit() {
    this.someInput.nativeElement.value = 'Whale!';
  }
}

ngAfterViewInitが起動すると、<input>の値は次のように設定されます。

Output
Whale!

親コンポーネントは、子DOM要素の値を設定できました。

子コンポーネントでのViewChildの使用

ViewChildを使用すると、子コンポーネントにアクセスしてメソッドを呼び出したり、子が使用できるインスタンス変数にアクセスしたりできます。

PupComponentがあるとします。

理想的には、コンポーネントを@angular/cliからgenerateに使用します。

  1. ng generate component pup --flat --skip-tests

このコマンドは、pup.component.tspup.component.css、およびpup.component.htmlファイルを作成します。 そして、コンポーネントをapp.module.tsに追加します。

app.module.ts
import { PupComponent } from './pup.component';
...
@NgModule({
  declarations: [
    AppComponent,
    PupComponent
  ],
  ...
})

次に、whoAmIメソッドをPupComponentに追加すると、次のメッセージが返されます。

pup.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-pup',
  templateUrl: './pup.component.html',
  styleUrs: ['./pup/component.css']
})
export class PupComponent implements OnInit {

  constructor() { }

  whoAmI() {
    return 'I am a pup component!';
  }

  ngOnInit(): void {
  }

}

次に、アプリテンプレートで子コンポーネントを参照します。 app.component.htmlの内容を次のように置き換えます。

app.component.html
<app-pup>pup works!</app-pup>

これで、ViewChildを使用して、親コンポーネントクラス内からwhoAmIメソッドを呼び出すことができます。 app.component.tsの内容を次のように置き換えます。

app.component.ts
import {
  Component,
  ViewChild,
  AfterViewInit
} from '@angular/core';
import { PupComponent } from './pup.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements AfterViewInit {
  @ViewChild(PupComponent) pup!: PupComponent;
  ngAfterViewInit() {
    console.log(this.pup.whoAmI()); // I am a pup component!
  }
}

ブラウザでアプリケーションを表示すると、コンソールログに次のように表示されます。

Output
I am a pup component!

親コンポーネントは、子コンポーネントのwhoAmIメソッドを呼び出すことができました。

結論

このチュートリアルでは、ViewChildを使用して、親コンポーネントクラスからディレクティブ、子コンポーネント、およびDOM要素にアクセスしました。

参照が動的に新しい要素に変更されると、ViewChildはその参照を自動的に更新します。

複数の子にアクセスする場合は、代わりにViewChildrenを使用します。

Angularについて詳しく知りたい場合は、Angularトピックページで演習とプログラミングプロジェクトを確認してください。