Для чего используется @ViewChildren?angular-50

@ViewChildren — это декоратор в Angular, который позволяет получить доступ к нескольким дочерним элементам или директивам текущего компонента. В отличие от @ViewChild, который работает с одним элементом, @ViewChildren возвращает QueryList — специальную коллекцию элементов, которая может обновляться динамически.

Основные случаи использования

1. Доступ к дочерним компонентам

import { Component, ViewChildren, QueryList } from '@angular/core';
import { ChildComponent } from './child.component';

@Component({
  selector: 'app-parent',
  template: `
    <app-child></app-child>
    <app-child></app-child>
  `
})
export class ParentComponent {
  @ViewChildren(ChildComponent) children: QueryList<ChildComponent>;
}

2. Доступ к DOM элементам по шаблонной переменной

@Component({
  template: `
    <div #item>Item 1</div>
    <div #item>Item 2</div>
  `
})
export class MyComponent {
  @ViewChildren('item') items: QueryList<ElementRef>;
}

3. Доступ к директивам

@Directive({ selector: '[myDirective]' })
export class MyDirective {}

@Component({
  template: `
    <div myDirective></div>
    <div myDirective></div>
  `
})
export class MyComponent {
  @ViewChildren(MyDirective) directives: QueryList<MyDirective>;
}

Особенности QueryList

  1. Динамическое обновление
    QueryList автоматически обновляется при изменении DOM (добавлении/удалении элементов).

  2. Методы и свойства:

    • length — количество элементов
    • first — первый элемент
    • last — последний элемент
    • changes — Observable для отслеживания изменений
    • forEach() — итерация по элементам
    • toArray() — преобразование в массив
ngAfterViewInit() {
  console.log(this.items.length); // Количество элементов

  this.items.changes.subscribe(() => {
    console.log('Коллекция изменилась');
  });
}

Жизненный цикл

Доступ к элементам возможен только после хука ngAfterViewInit. Попытка доступа раньше (например, в ngOnInit) приведет к пустой коллекции.

Практические примеры использования

1. Управление фокусом на группе элементов

@ViewChildren('input') inputs: QueryList<ElementRef>;

setFocusToNext() {
  const inputsArray = this.inputs.toArray();
  const activeIndex = inputsArray.findIndex(i => i.nativeElement === document.activeElement);

  if (activeIndex < inputsArray.length - 1) {
    inputsArray[activeIndex + 1].nativeElement.focus();
  }
}

2. Взаимодействие с группой дочерних компонентов

@ViewChildren(ChildComponent) children: QueryList<ChildComponent>;

disableAllChildren() {
  this.children.forEach(child => child.disable());
}

3. Реакция на изменения в DOM

@ViewChildren('item') items: QueryList<ElementRef>;

ngAfterViewInit() {
  this.items.changes.subscribe(items => {
    console.log(`Количество элементов изменилось: ${items.length}`);
  });
}

Отличие от @ContentChildren

Важно не путать @ViewChildren с @ContentChildren:

  • @ViewChildren — для элементов, которые являются частью шаблона компонента
  • @ContentChildren — для проекцированного контента (ng-content)

Резюмируем

@ViewChildren используется для получения доступа к коллекции дочерних элементов, компонентов или директив, объявленных в шаблоне текущего компонента. Это мощный инструмент для взаимодействия с динамическими коллекциями элементов, с автоматическим отслеживанием изменений в DOM через QueryList.