Tutorial

AngularでViewChildを使用して、子コンポーネント、ディレクティブ、DOM 要素にアクセスする方法

Angular

はじめに

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

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

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

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

SharkDirectiveがあるとします。

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

  • ng generate directive shark

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

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

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

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を追加します。

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

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

Output
Shark Fin!

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

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
<input #someInput placeholder="Your favorite sea creature">

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

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

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

  • ng generate component child --flat

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

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

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

child.component.ts
whoAmI() {
  return 'I am a child component!';
}

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

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

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

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!
  }
}

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

Output
I am a child component!

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

まとめ

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

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

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

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

Creative Commons License