Доступ к компонентам, директивам и элементам DOM в Angular

В руководстве мы рассмотрим, как работает декоратор ViewChild в Angular.

Иногда возникает необходимость получить доступ к директиве, дочернему компоненту или элементу 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: , , ,

Добавить комментарий