← Back to Articles         
View Queries Such as ViewChild

View Queries Such as ViewChild

Published on 29 Sep 2026     11 min read Angular
Angular Components

What Are View Queries Such as ViewChild?

What is a View Query?

A view query allows an Angular component to obtain a reference to something inside its own template/view.

For example, a parent template contains:

<app-counter></app-counter>

The parent may need direct access to that Counter component instance.

A view query allows Angular to find it.

Parent Component
       │
       │ View Query
       ▼
Parent Template
       │
       └── Counter Child
               │
               ▼
        Counter instance

Common view-query APIs include:

viewChild()
viewChildren()

and the traditional decorator APIs:

@ViewChild()
@ViewChildren()

What is ViewChild?

ViewChild allows a component to get a reference to one matching element, directive, or child component from its own view.

A common example is:

Parent directly calls a method on its child component.

For example:

Counter Component
   │
   ├── Increment
   └── Reset

Parent
   │
   └── Calls child.reset()

Why Do We Need View Queries?

Normally, components should communicate through:

Parent ── input() ──► Child

Parent ◄─ output() ── Child

But sometimes the parent needs direct access to something in its view.

Examples:

  • Call a child component method.
  • Focus an input element.
  • Access a DOM element.
  • Read a directive instance.
  • Access multiple child components.
  • Interact with a third-party UI component.

That's where view queries are useful.


Full Code Example – Modern viewChild()

Let's create a parent that directly resets a child counter.

counter.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-counter',
  templateUrl: './counter.html'
})
export class Counter {

  count = 0;

  increment() {
    this.count++;
  }

  reset() {
    this.count = 0;
  }
}

counter.html

<h2>Count: {{ count }}</h2>

<button (click)="increment()">
  Increment
</button>

app.ts

import {
  Component,
  viewChild
} from '@angular/core';

import { Counter } from './counter/counter';

@Component({
  selector: 'app-root',
  imports: [Counter],
  templateUrl: './app.html'
})
export class App {

  counter = viewChild(Counter);

  resetCounter() {

    this.counter()?.reset();

  }
}

app.html

<h1>Counter Application</h1>

<app-counter></app-counter>

<br>

<button (click)="resetCounter()">
  Reset Counter
</button>

Code Explanation

The parent template contains:

<app-counter></app-counter>

Therefore, Counter is part of the parent's view.

The parent creates a view query:

counter = viewChild(Counter);

Angular searches the parent's view for the matching Counter component.

Conceptually:

App
 │
 │ viewChild(Counter)
 │
 ▼
App Template
 │
 └── <app-counter>
          │
          ▼
    Counter instance

The parent can then access the child:

this.counter()

and call:

this.counter()?.reset();

Therefore:

Parent
  │
  │ viewChild()
  ▼
Counter
  │
  │ reset()
  ▼
count = 0

Why counter()?

Modern:

counter = viewChild(Counter);

returns a signal-based query result.

Therefore, you read the current result using:

this.counter()

Since the child might not currently exist, the result can be undefined.

That's why the example uses:

this.counter()?.reset();

Required viewChild()

If you know the queried child must exist, modern Angular also supports a required query.

Full Example

import {
  Component,
  viewChild
} from '@angular/core';

import { Counter } from './counter/counter';

@Component({
  selector: 'app-root',
  imports: [Counter],
  template: `
    <app-counter></app-counter>

    <button (click)="resetCounter()">
      Reset
    </button>
  `
})
export class App {

  counter = viewChild.required(Counter);

  resetCounter() {
    this.counter().reset();
  }
}

Now:

this.counter()

is expected to provide the Counter instance.


Traditional @ViewChild()

Existing Angular applications commonly use the decorator-based @ViewChild() API.

Full Code

counter.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-counter',
  template: `
    <h2>Count: {{ count }}</h2>

    <button (click)="increment()">
      Increment
    </button>
  `
})
export class Counter {

  count = 0;

  increment() {
    this.count++;
  }

  reset() {
    this.count = 0;
  }
}

app.ts

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

import { Counter } from './counter/counter';

@Component({
  selector: 'app-root',
  imports: [Counter],
  template: `
    <app-counter></app-counter>

    <button (click)="resetCounter()">
      Reset
    </button>
  `
})
export class App {

  @ViewChild(Counter)
  counter!: Counter;

  resetCounter() {
    this.counter.reset();
  }
}

Modern vs Traditional

Modern Angular:

counter = viewChild(Counter);

Access:

this.counter()

Traditional:

@ViewChild(Counter)
counter!: Counter;

Access:

this.counter

So remember:

Traditional Modern
@ViewChild() viewChild()
Decorator query Signal-based query
this.counter this.counter()
Common in existing applications Preferred modern API

Accessing an HTML Element

View queries aren't limited to Angular components.

They can also access DOM elements.

For example, suppose you want to focus an input box.


Full Code Example

app.ts

import {
  Component,
  ElementRef,
  viewChild
} from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.html'
})
export class App {

  nameInput =
    viewChild<ElementRef<HTMLInputElement>>('nameInput');

  focusInput() {

    this.nameInput()?.nativeElement.focus();

  }
}

app.html

<input
  #nameInput
  type="text"
  placeholder="Enter your name">

<button (click)="focusInput()">
  Focus Input
</button>

Code Explanation

The template contains:

#nameInput

This is a template reference variable.

The view query searches for it:

viewChild<ElementRef<HTMLInputElement>>('nameInput');

Then:

this.nameInput()

returns the queried reference.

ElementRef gives access to the native DOM element:

.nativeElement

Then:

.focus()

focuses the textbox.

Flow:

#nameInput
     │
     ▼
viewChild('nameInput')
     │
     ▼
ElementRef
     │
     ▼
nativeElement
     │
     ▼
focus()

Direct DOM manipulation should be kept limited; prefer Angular bindings and component APIs when they can express the same behavior.


What is viewChildren()?

viewChild() gets one matching result.

viewChild(...)

viewChildren() gets multiple matching results.

viewChildren(...)

For example:

<app-product></app-product>

<app-product></app-product>

<app-product></app-product>

You can query all three Product components.


Full viewChildren() Example

product.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-product',
  template: `
    <p>{{ selected ? 'Selected' : 'Not Selected' }}</p>
  `
})
export class Product {

  selected = false;

  select() {
    this.selected = true;
  }
}

app.ts

import {
  Component,
  viewChildren
} from '@angular/core';

import { Product } from './product/product';

@Component({
  selector: 'app-root',
  imports: [Product],
  templateUrl: './app.html'
})
export class App {

  products = viewChildren(Product);

  selectAll() {

    this.products().forEach(product => {
      product.select();
    });

  }
}

app.html

<app-product></app-product>

<app-product></app-product>

<app-product></app-product>

<button (click)="selectAll()">
  Select All
</button>

viewChild() vs viewChildren()

viewChild() viewChildren()
Finds one result Finds multiple results
Child component Multiple child components
Element/directive/component Multiple elements/directives/components
Returns a query signal Returns a query signal containing results

Easy way to remember:

viewChild()
     │
     ▼
   ONE


viewChildren()
     │
     ▼
   MANY

View Query vs Content Query

This distinction is useful for interviews.

A view query searches the component's own template.

Component
    │
    └── Own Template
           │
           └── viewChild()

Angular also has content queries such as:

contentChild()
contentChildren()

These query content projected into the component, rather than elements created directly in its own template.

viewChild()
     │
     └── My own view/template


contentChild()
     │
     └── Projected content

This connects directly to the ng-content concept you just learned.


Advantages of View Queries

Direct Child Access

A parent can directly access a child component when imperative control is genuinely needed.

DOM Element Access

Useful for operations such as:

focus()
scroll()
measurements

Third-Party Components

Useful when libraries expose methods that must be called directly.

Multiple Children

viewChildren() can query multiple child instances.

Reactive Modern API

Modern query functions such as viewChild() return signals, so query results work naturally with Angular's reactive APIs.


Disadvantages

Increased Coupling

Calling:

this.counter()?.reset();

means the parent knows details about the child.

That creates stronger coupling than normal input/output communication.

Can Be Overused

You should not use ViewChild simply because you want to pass ordinary data.

For normal communication:

Parent → Child

prefer:

input()

For:

Child → Parent

prefer:

output()

Direct DOM Access

Using:

ElementRef.nativeElement

too frequently can bypass Angular's normal declarative approach and make components harder to maintain.


input() vs output() vs viewChild()

This is important.

Requirement Use
Parent sends data to child input()
Child sends event to parent output()
Parent directly accesses child viewChild()
Parent accesses multiple children viewChildren()
Access projected child/content contentChild() / contentChildren()

Think of it as:

             PARENT

               │
               │ input()
               ▼

              CHILD

               │
               │ output()
               ▼

             PARENT


Parent ── viewChild() ──► Direct Child Reference

Key Points

ng-content

  • Used for content projection.
  • Parent provides content.
  • Child determines where it appears.
  • Basic syntax:
<ng-content></ng-content>
  • Multiple slots use:
<ng-content select="[header]"></ng-content>

View Queries

  • Used to query items in a component's own view.
  • Modern APIs:
viewChild()
viewChildren()
  • Traditional APIs:
@ViewChild()
@ViewChildren()
  • viewChild() → one result.
  • viewChildren() → multiple results.
  • Can query components, directives, and template references.
  • Prefer input()/output() for normal component communication; use view queries when direct access is actually required.

Interview Questions & Answers

Q1. What is ng-content?

ng-content is an Angular placeholder used for content projection. It specifies where content supplied by a parent should be rendered inside a child component.


Q2. What is a view query?

A view query allows a component to retrieve references to elements, directives, or child components from its own template.


Q3. What is ViewChild?

ViewChild retrieves a reference to a single matching element, directive, or child component from the component's view.

Modern Angular provides:

viewChild()

while existing applications commonly use:

@ViewChild()

Q4. What is the difference between viewChild() and viewChildren()?

viewChild() retrieves one matching result, while viewChildren() retrieves all matching results.


Q5. What is the difference between input() and viewChild()?

input() is used to pass data from parent to child.

product = input<Product>();

viewChild() gives the parent direct access to a child component or view element.

counter = viewChild(Counter);

Q6. Can ViewChild access an HTML element?

Yes. A template reference variable can be queried using viewChild() and accessed through ElementRef when direct DOM access is necessary.


Q7. What is the difference between a view query and a content query?

A view query searches the component's own template:

viewChild()
viewChildren()

A content query searches content projected into the component:

contentChild()
contentChildren()

Q8. Should ViewChild be used for normal parent-child communication?

Usually no. Prefer:

Parent → Child  = input()

Child → Parent  = output()

Use viewChild() when the parent genuinely needs a direct reference to a child component, directive, or view element.

Interview-Ready Answer

ng-content is used for content projection and defines where parent-provided content appears inside a child component. View queries such as viewChild() and viewChildren() allow a component to obtain references to components, directives, or elements in its own template. Modern Angular provides signal-based query functions, while existing applications commonly use the decorator-based @ViewChild() and @ViewChildren() APIs.

@ViewChildren() – One More Simple Example

Here is a practical example: a parent has multiple child Product components, and clicking “Apply Discount to All” calls a method on every child.

Full Code

product.ts — Child Component

import { Component, input } from '@angular/core';

@Component({
  selector: 'app-product',
  templateUrl: './product.html'
})
export class Product {

  name = input.required<string>();
  price = input.required<number>();

  discountPrice = 0;

  applyDiscount() {
    this.discountPrice = this.price() * 0.9;
  }
}

product.html

<div>
  <h3>{{ name() }}</h3>

  <p>Original Price: ₹{{ price() }}</p>

  @if (discountPrice > 0) {
    <p>Discount Price: ₹{{ discountPrice }}</p>
  }
</div>

app.ts — Parent Component

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

import { Product } from './product/product';

@Component({
  selector: 'app-root',
  imports: [Product],
  templateUrl: './app.html'
})
export class App {

  @ViewChildren(Product)
  products!: QueryList<Product>;

  applyDiscountToAll() {

    this.products.forEach(product => {
      product.applyDiscount();
    });

  }
}

app.html

<h1>Product List</h1>

<app-product
  name="Laptop"
  [price]="50000">
</app-product>

<app-product
  name="Mobile"
  [price]="30000">
</app-product>

<app-product
  name="Tablet"
  [price]="20000">
</app-product>

<button (click)="applyDiscountToAll()">
  Apply 10% Discount to All
</button>

Explanation

The parent contains three instances of:

<app-product>

So conceptually:

App
 │
 ├── Product → Laptop
 ├── Product → Mobile
 └── Product → Tablet

We want the parent to access all three child component instances.

That's where @ViewChildren() is useful.

1. Query all Product children

@ViewChildren(Product)
products!: QueryList<Product>;

Angular searches the parent's view for all Product components.

The result is stored in a:

QueryList<Product>

Conceptually:

@ViewChildren(Product)
        │
        ▼
QueryList<Product>
        │
        ├── Product → Laptop
        ├── Product → Mobile
        └── Product → Tablet

2. Loop through all children

When the button is clicked:

<button (click)="applyDiscountToAll()">

the parent executes:

applyDiscountToAll() {

  this.products.forEach(product => {
    product.applyDiscount();
  });

}

this.products contains all three child component instances.

Therefore:

this.products
      │
      ├── Laptop  → applyDiscount()
      ├── Mobile  → applyDiscount()
      └── Tablet  → applyDiscount()

3. Parent calls the child's method

Each child contains:

applyDiscount() {
  this.discountPrice = this.price() * 0.9;
}

So the result becomes:

Laptop
₹50,000 → ₹45,000

Mobile
₹30,000 → ₹27,000

Tablet
₹20,000 → ₹18,000

What is QueryList?

With traditional @ViewChildren(), Angular returns a QueryList, which represents a collection of matching children.

@ViewChildren(Product)
products!: QueryList<Product>;

You can work with it similarly to a collection.

For example:

this.products.forEach(product => {
  console.log(product);
});

You can also check:

console.log(this.products.length);

In our example:

3

@ViewChild() vs @ViewChildren()

The difference becomes very clear with this example.

One child

@ViewChild(Product)
product!: Product;
Parent
  │
  └── Product

Multiple children

@ViewChildren(Product)
products!: QueryList<Product>;
Parent
  │
  ├── Product
  ├── Product
  └── Product

So remember:

@ViewChild
     ↓
    ONE


@ViewChildren
     ↓
    MANY

Interview-Ready Answer

@ViewChildren() is used when a component needs references to multiple matching child components, directives, or elements in its view. It returns a QueryList. For example, if a parent contains multiple Product components, @ViewChildren(Product) can retrieve all of them, allowing the parent to iterate through the children and call methods such as applyDiscount() on each instance.

 

← Back to Articles