はじめに

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

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

ディレクティブに対してViewChildを使用する

viewchild illustration for: ディレクティブに対してViewChildを使用する

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

SharkDirectiveがあるとします。

理想的には、@angular/cliを使用してディレクティブを生成します。

				
					
ng generate directive shark

				
			

それ以外の場合は、app.module.tsに手動で追加する必要があります。

				
					
[label app.module.ts]

<^>import { SharkDirective } from './shark.directive';<^>

...

@NgModule({

  declarations: [

    AppComponent,

    <^>SharkDirective<^>

  ],

  ...

})

				
			

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

				
					
[label 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);

  }

}

				
			

次に、それを使用してコンポーネントテンプレートでFinSharkを追加します。

				
					
[label app.component.html]

<span <^>appShark<^>>Fin!</span>

				
			

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

				
					
[secondary_label Output]

Shark Fin!

				
			

これで、SharkDirectivecreatureインスタンス変数にアクセスして、extraCreatureインスタンス変数にその値を設定できるようになりました。

				
					
[label 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!」というメッセージが表示されます。ただし、コンソールログでは、次のように表示されます。

				
					
[secondary_label Output]

Dolphin

				
			

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

DOM要素に対してViewChildを使用する

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

#someInput参照変数を持つ<input>がテンプレートにあるとします。

				
					
[label app.component.html]

&lt;input &lt;^&gt;#someInput&lt;^&gt; placeholder="Your favorite sea creature"&gt;

				
			

これで、ViewChildを使用して<input>にアクセスし、を設定できます。

				
					
[label 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>の値は次のように設定されます。

				
					
[secondary_label Output]

Whale!

				
			

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

子コンポーネントに対してViewChildを使用する

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

ChildComponentがあるとします。理想的には、@angular/cliを使用してコンポーネントを生成します。

				
					
ng generate component child --flat

				
			

それ以外の場合は、child.component.csschild.component.htmlファイルを作成し、app.module.tsに手動で追加する必要があります。

				
					
[label app.module.ts]

&lt;^&gt;import { ChildComponent } from './child.component';&lt;^&gt;

...

@NgModule({

  declarations: [

    AppComponent,

    &lt;^&gt;ChildComponent&lt;^&gt;

  ],

  ...

})

				
			

メッセージを返すChildComponentwhoAmIメソッドを追加します。

				
					
[label child.component.ts]

whoAmI() {

  return 'I am a child component!';

}

				
			

次に、アプリテンプレート内のコンポーネントを参照します。

				
					
[label app.component.html]

&lt;app-child&gt;child works!&lt;/app-child&gt;

				
			

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

				
					
[label app.component.ts]

import {

  Component,

  ViewChild,

  AfterViewInit

} from '@angular/core';

import { ChildComponent } from './child.component';



@Component({

  selector: 'app-root',

  templateUrl: './app.component.html',

  styleUrls: ['./app.component.css'],

})

export class AppComponent implements AfterViewInit {

  @ViewChild(ChildComponent) child: ChildComponent;

  ngAfterViewInit() {

    console.log(this.child.whoAmI()); // I am a child component!

  }

}

				
			

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

				
					
[secondary_label Output]

I am a child component!

				
			

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

まとめ

ViewChildを使用して、親コンポーネントクラスからディレクティブ、子コンポーネント、DOM要素にアクセスする方法を学びました。

参照が新しい要素に動的に変更された場合は、ViewChildによってその参照は自動的に更新されます。

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

Angular の詳細については、Angular トピックページで演習とプログラミングプロジェクトをご覧ください。