Введение

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

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

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

viewchild illustration for: Использование 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]

&lt;input &lt;^&gt;#someInput&lt;^&gt; placeholder="Your favorite sea creature"&gt;

				
			

Теперь мы можем получить доступ к <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]

&lt;^&gt;import { ChildComponent } from './child.component';&lt;^&gt;

...

@NgModule({

  declarations: [

    AppComponent,

    &lt;^&gt;ChildComponent&lt;^&gt;

  ],

  ...

})

				
			

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

				
					
[label child.component.ts]

whoAmI() {

  return 'I am a child component!';

}

				
			

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

				
					
[label app.component.html]

&lt;app-child&gt;child works!&lt;/app-child&gt;

				
			

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