Используйте ViewChild в Angular для доступа к дочернему компоненту, директиве или элементу DOM

Введение

В этой статье мы познакомим вас с декоратором 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);   } } 

Затем мы добавим Shark в Fin, используя его в шаблоне компонента:

app.component.html

<span appShark>Fin!</span> 

При просмотре приложения в браузере оно будет выглядеть так:

OutputShark Fin! 

Теперь мы можем получить доступ к переменной экземпляра creature директивы SharkDirective и задать переменную экземпляра 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!", сообщение. Однако в журнале консоли отображается следующее:

OutputDolphin 

Родительскому компоненту удалось получить доступ к значению из директивы.

Использование ViewChild с элементами DOM

ViewChild предоставляет возможность доступа к элементам модели DOM, имеющим шаблонную переменную.

Допустим в нашем шаблоне имеется <input> с шаблонной переменной #someInput:

app.component.html

<input #someInput placeholder="Your favorite sea creature"> 

Теперь мы можем получить доступ к <input> с помощью ViewChild и задать значение:

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> задается следующее значение:

OutputWhale! 

Родительскому компоненту удалось задать значение дочернего элемента DOM.

Использование ViewChild с дочерними компонентами

ViewChild обеспечивает возможность доступа к дочернему компоненту и методам вызова или доступа к переменным экземпляра, которые доступны дочернему элементу.

Допустим, у нас имеется компонент ChildComponent. В идеале мы используем @angular/cli для генерирования компонента:

  • ng generate component child --flat

В противном случае вам может понадобиться создать файлы child.component.css и child.component.html и вручную добавить их в app.module.ts:

app.module.ts

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

Мы добавим метод whoAmI в компонент ChildComponent, который возвращает следующее сообщение:

child.component.ts

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

Далее мы разместим ссылку на компонент в нашем шаблоне приложения:

app.component.html

<app-child>child works!</app-child> 

Теперь мы можем вызвать метод whoAmI внутри класса родительского компонента с помощью ViewChild, как показано здесь:

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

При просмотре приложения в браузере отображается журнал консоли:

OutputI am a child component! 

Родительскому компоненту удалось вызвать метод whoAmI дочернего компонента.

Заключение

Вы научились использовать ViewChild для доступа к директиве, дочернему компоненту и элементу DOM из класса родительского компонента.

Если шаблон динамически изменится на новый элемент, ViewChild автоматически обновит шаблон.

Если вам требуется доступ к нескольким дочерним элементам, вам следует использовать метод ViewChildren.

Если вы хотите узнать больше об Angular, посмотрите нашу страницу тем по Angular, где вы найдете упражнения и проекты по программированию.