Table of Contents
Введение
В этой статье мы познакомим вас с декоратором Angular ViewChild.
В некоторых ситуациях вам может потребоваться доступ к директиве, дочернему компоненту или элементу DOM из класса родительского компонента. Декоратор ViewChild возвращает первый элемент, совпадающий с заданной директивой, компонентом или селектором шаблонов.
Использование ViewChild с директивами
ViewChild открывает возможность доступа к директивам.
Допустим, у нас имеется директива SharkDirective.
В идеале мы используем @angular/cli для генерирования директивы:
ng generate directive shark
В противном случае необходимо добавить ее вручную в app.module.ts:
[label app.module.ts]
<^>import { SharkDirective } from './shark.directive';<^>
...
@NgModule({
declarations: [
AppComponent,
<^>SharkDirective<^>
],
...
})
Наша директива будет искать элементы с атрибутом appShark и добавлять в начало текста элемента слово Shark:
[label 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, используя его в шаблоне компонента:
[label app.component.html]
<span <^>appShark<^>>Fin!</span>
При просмотре приложения в браузере оно будет выглядеть так:
[secondary_label Output]
Shark Fin!
Теперь мы можем получить доступ к переменной экземпляра creature директивы SharkDirective и задать переменную экземпляра extraCreature с ее значением:
[label 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!", сообщение. Однако в журнале консоли отображается следующее:
[secondary_label Output]
Dolphin
Родительскому компоненту удалось получить доступ к значению из директивы.
Использование ViewChild с элементами DOM
ViewChild предоставляет возможность доступа к элементам модели DOM, имеющим шаблонную переменную.
Допустим в нашем шаблоне имеется <input> с шаблонной переменной #someInput:
[label app.component.html]
<input <^>#someInput<^> placeholder="Your favorite sea creature">
Теперь мы можем получить доступ к <input> с помощью ViewChild и задать значение:
[label 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> задается следующее значение:
[secondary_label Output]
Whale!
Родительскому компоненту удалось задать значение дочернего элемента DOM.
Использование ViewChild с дочерними компонентами
ViewChild обеспечивает возможность доступа к дочернему компоненту и методам вызова или доступа к переменным экземпляра, которые доступны дочернему элементу.
Допустим, у нас имеется компонент ChildComponent. В идеале мы используем @angular/cli для генерирования компонента:
ng generate component child --flat
В противном случае вам может понадобиться создать файлы child.component.css и child.component.html и вручную добавить их в app.module.ts:
[label app.module.ts]
<^>import { ChildComponent } from './child.component';<^>
...
@NgModule({
declarations: [
AppComponent,
<^>ChildComponent<^>
],
...
})
Мы добавим метод whoAmI в компонент ChildComponent, который возвращает следующее сообщение:
[label child.component.ts]
whoAmI() {
return 'I am a child component!';
}
Далее мы разместим ссылку на компонент в нашем шаблоне приложения:
[label app.component.html]
<app-child>child works!</app-child>
Теперь мы можем вызвать метод whoAmI внутри класса родительского компонента с помощью ViewChild, как показано здесь:
[label 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!
}
}
При просмотре приложения в браузере отображается журнал консоли:
[secondary_label Output]
I am a child component!
Родительскому компоненту удалось вызвать метод whoAmI дочернего компонента.
Заключение
Вы научились использовать ViewChild для доступа к директиве, дочернему компоненту и элементу DOM из класса родительского компонента.
Если шаблон динамически изменится на новый элемент, ViewChild автоматически обновит шаблон.
Если вам требуется доступ к нескольким дочерним элементам, вам следует использовать метод ViewChildren.
Если вы хотите узнать больше об Angular, посмотрите нашу страницу тем по Angular, где вы найдете упражнения и проекты по программированию.