Доступ к компонентам, директивам и элементам DOM в Angular
Development | Комментировать запись
Иногда возникает необходимость получить доступ к директиве, дочернему компоненту или элементу DOM из класса родительского компонента. Декоратор ViewChild возвращает первый элемент, который отвечает заданной директиве, компоненту или селектору ссылки на шаблон.
Доступ к директивам с помощью ViewChild
ViewChild позволяет получить доступ к директивам.
Давайте представим, что у нас есть условная директива SharkDirective.
В идеале для создания директивы вы должны использовать @angular/cli:
ng generate directive shark
Иначе может потребоваться вручную добавить ее в 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>
При просмотре приложения в браузере вы получит:
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!». Однако в логе консоли будет отображаться:
Dolphin
Родительский компонент смог получить доступ к значению из директивы.
Доступ к элементам DOM с помощью ViewChild
ViewChild позволяет получить доступ к родным элементам DOM, имеющим ссылочную переменную шаблона.
Давайте предположим, что в нашем шаблоне со ссылочной переменной #someInput есть <input>:
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> будет установлено следующее значение:
Whale!
С помощью ViewChild родительский компонент смог установить значение дочернего элемента 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-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!
}
}
При просмотре приложения в браузере в логе консоли будет отображаться сообщение:
I am a child component!
С помощью ViewChild родительский компонент смог вызвать метод whoAmI дочернего компонента.
Заключение
В этом руководстве вы узнали, как использовать ViewChild для доступа к директивам, дочерним компонентам и элементу DOM из класса родительского компонента.
Если ссылка динамически изменяется на новый элемент, ViewChild автоматически обновит свою ссылку.
Если вы хотите получить доступ к нескольким дочерним объектам, вместо ViewChild используйте декоратор ViewChildren.
Узнать больше об Angular можно в нашем Информатории.
Tags: Angular, AngularJS, DOM, ViewChild