Tutorial

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

Published on November 23, 2020
Default avatar

By Alligator.io

Русский
Используйте 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, где вы найдете упражнения и проекты по программированию.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Alligator.io

author



Still looking for an answer?

Ask a questionSearch for more help

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!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel