🅰️ Angular Q44 / 125

Difference between ViewChild and ViewChildren?

AI-Powered Answer ✓ Answered

In Angular, `ViewChild` and `ViewChildren` are property decorators used to query elements from the view DOM. They allow a component class to get references to elements, components, or directives that are part of its own view. The primary difference lies in the number of elements they can query and their return types.

ViewChild

ViewChild is used to query and get the first matching element, component, or directive from the DOM in the component's template. It returns a single instance of the matched element. The query result is available in the ngAfterViewInit lifecycle hook, which runs once after the component's view has been fully initialized.

typescript
import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';

@Component({
  selector: 'app-view-child-example',
  template: `
    <h3 #myHeading>Hello ViewChild!</h3>
    <input #myInput type="text" placeholder="Enter text">
  `
})
export class ViewChildExampleComponent implements AfterViewInit {
  @ViewChild('myHeading') myHeadingElement: ElementRef;
  @ViewChild('myInput') myInputElement: ElementRef;

  ngAfterViewInit() {
    console.log('Heading text:', this.myHeadingElement.nativeElement.textContent);
    this.myInputElement.nativeElement.focus();
  }
}

ViewChildren

ViewChildren is used to query and get all matching elements, components, or directives from the DOM in the component's template. It returns a QueryList of instances. A QueryList is a collection that stores a list of items. When the state of the application changes and a child element is added or removed, the QueryList automatically updates its entries. It also provides a changes observable that you can subscribe to for reactive updates.

typescript
import { Component, ViewChildren, ElementRef, AfterViewInit, QueryList } from '@angular/core';

@Component({
  selector: 'app-view-children-example',
  template: `
    <div *ngFor="let item of items">
      <p #myParagraph>{{ item }}</p>
    </div>
    <button (click)="addItem()">Add Item</button>
  `
})
export class ViewChildrenExampleComponent implements AfterViewInit {
  items = ['Item 1', 'Item 2', 'Item 3'];
  @ViewChildren('myParagraph') myParagraphs: QueryList<ElementRef>;

  ngAfterViewInit() {
    this.myParagraphs.forEach((paragraph, index) => {
      console.log(`Paragraph ${index + 1} text:`, paragraph.nativeElement.textContent);
    });

    // Subscribe to changes if elements are added/removed dynamically
    this.myParagraphs.changes.subscribe(list => {
      console.log('Paragraphs updated:', list.toArray().map(el => el.nativeElement.textContent));
    });
  }

  addItem() {
    this.items.push(`Item ${this.items.length + 1}`);
  }
}

Key Differences

FeatureViewChildViewChildren
Return TypeSingle instance (ElementRef, component, or directive)QueryList<T> (a collection of instances)
Query ResultThe first matching elementAll matching elements
AvailabilityAvailable in `ngAfterViewInit` (synchronously)The `QueryList` is available in `ngAfterViewInit`. The `changes` observable provides updates if elements are added/removed.
ReactivityNot inherently reactive; refers to a static element at query time.Reactive; the `QueryList` automatically updates, and its `changes` observable can be subscribed to.
Use CaseAccessing a single known element (e.g., a specific input field, a single child component).Accessing a collection of dynamic or repeated elements (e.g., items within an `ngFor` loop, multiple child components of the same type).

When to Use Which

  • Use ViewChild when:
  • You need to interact with a single, specific DOM element, component, or directive.
  • To focus an input field on initialization.
  • To call a method on a single child component.
  • To get a reference to a static element in your template that is not expected to change.
  • Use ViewChildren when:
  • You need to interact with multiple instances of the same element, component, or directive.
  • When dealing with dynamically added or removed elements (e.g., within an ngFor loop).
  • To perform an action on all child components of a certain type.
  • To subscribe to changes in a collection of view elements to react to dynamic updates.