// Tutorial //

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

Published on November 23, 2020
Default avatar
By Alligator.io
Developer and author at DigitalOcean.
Русский
Используйте ViewChild в Angular для доступа к дочернему компоненту, директиве или элементу DOM

Введение

В этой статье мы познакомим вас с декоратором Angular ViewChild.

В некоторых ситуациях вам может потребоваться доступ к директиве, дочернему компоненту или элементу DOM из класса родительского компонента. Декоратор ViewChild возвращает первый элемент, совпадающий с заданной директивой, компонентом или селектором шаблонов.

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

ViewChild открывает возможность доступа к директивам.

Допустим, у нас имеется директива SharkDirective.

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

  1. 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>

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

Output
Shark 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!", сообщение. Однако в журнале консоли отображается следующее:

Output
Dolphin

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

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

Output
Whale!

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

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

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

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

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

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

Output
I am a child component!

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

Заключение

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

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

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

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

If you’ve enjoyed this tutorial and our broader community, consider checking out our DigitalOcean products which can also help you achieve your development goals.

Learn more here


About the authors
Default avatar
Developer and author at DigitalOcean.

Default avatar
Developer and author at DigitalOcean.

Still looking for an answer?

Was this helpful?
Leave a comment

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!