← Back to Articles         
ViewChild and ContentChild

ViewChild and ContentChild

Published on 29 Sep 2026     9 min read Angular
Angular Components

ViewChild vs ContentChild in Angular

The main difference is where Angular searches.

ViewChild searches inside the component's own template.
ContentChild searches content projected into the component through <ng-content>.

ViewChild
   ↓
My own template


ContentChild
   ↓
Content received from parent
through <ng-content>

1. What is ViewChild?

ViewChild is a view query used to get a reference to an element, directive, or child component that exists inside the component's own template.

For example:

App Component
     │
     └── app.html
           │
           └── <app-counter>
                     ↑
                ViewChild

The <app-counter> is directly declared in App's template, so ViewChild can query it.


Why Do We Need ViewChild?

Use it when the component needs direct access to something it owns in its template.

Common examples:

  • Call a child component method
  • Focus an input
  • Access a directive
  • Access a DOM element
  • Control a third-party component

Full @ViewChild Example

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],
  templateUrl: './app.html'
})
export class App {

  @ViewChild(Counter)
  counter!: Counter;

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

app.html

<h1>Counter Application</h1>

<app-counter></app-counter>

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

ViewChild Code Explanation

The important part is:

<app-counter></app-counter>

This component exists directly inside App's own template.

Therefore:

@ViewChild(Counter)
counter!: Counter;

can find it.

Then the parent can call:

this.counter.reset();

Flow:

App Component
     │
     │ @ViewChild(Counter)
     ▼
App's own template
     │
     └── <app-counter>
              │
              ▼
       Counter instance
              │
              ▼
           reset()

2. What is ContentChild?

ContentChild is a content query used to get a reference to content that was provided by another component and projected through <ng-content>.

This is the important difference.

Suppose we have:

<app-card>

    <app-product></app-product>

</app-card>

Product is supplied by the parent to Card.

Inside Card:

<div class="card">

    <ng-content></ng-content>

</div>

The Product component is not originally declared inside Card's template.

It is projected into Card.

Therefore, Card can query it using:

@ContentChild(Product)

Why Do We Need ContentChild?

Sometimes a reusable component accepts projected content and also needs to interact with that content.

For example:

Card
 └── Projected Product

Tab
 └── Projected Tab Content

Dialog
 └── Projected Form

Panel
 └── Projected Component

ContentChild allows the container component to obtain a reference to that projected child.


Full @ContentChild Example

Let's create:

App
 │
 └── Card
       │
       └── Projected Product

product.ts

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

@Component({
  selector: 'app-product',
  template: `
    <h2>Laptop</h2>
    <p>Price: ₹50,000</p>
  `
})
export class Product {

  showMessage() {
    alert('Product method called');
  }
}

card.ts

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

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

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

  @ContentChild(Product)
  product!: Product;

  callProduct() {
    this.product.showMessage();
  }
}

card.html

<div class="card">

  <h2>Card Component</h2>

  <ng-content></ng-content>

  <button (click)="callProduct()">
    Call Product Method
  </button>

</div>

app.ts

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

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

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

app.html

<h1>Product Page</h1>

<app-card>

  <app-product></app-product>

</app-card>

ContentChild Code Explanation

Look carefully at app.html:

<app-card>

  <app-product></app-product>

</app-card>

Product is being passed into Card as content.

Card receives it through:

<ng-content></ng-content>

So the relationship is:

App
 │
 │ creates Product
 ▼
<app-card>
    <app-product>
</app-card>

        │
        │ Content Projection
        ▼

Card Template

<div>
    <ng-content></ng-content>
</div>

Inside Card, we use:

@ContentChild(Product)
product!: Product;

Angular searches the projected content for Product.

Then Card can call:

this.product.showMessage();

The Most Important Difference

Consider this component:

card.html

<app-header></app-header>

<ng-content></ng-content>

And the parent:

<app-card>

  <app-product></app-product>

</app-card>

Now there are two different types of children:

Card
│
├── Header
│     └── Created in Card's own template
│
└── Product
      └── Supplied/projected by parent

Therefore:

@ViewChild(Header)
header!: Header;

finds:

<app-header>

because it belongs to Card's view.

But:

@ContentChild(Product)
product!: Product;

finds:

<app-product>

because it was projected into Card.


Visual Explanation

This is the easiest way to remember it:

                 CARD COMPONENT
                       │
          ┌────────────┴────────────┐
          │                         │
      OWN TEMPLATE             PROJECTED CONTENT
          │                         │
          ▼                         ▼
   <app-header>               <app-product>
          ▲                         ▲
          │                         │
      ViewChild                ContentChild

Or:

ViewChild
   │
   └── "What is inside MY template?"


ContentChild
   │
   └── "What content was GIVEN TO ME?"

Full Combined Example

This example shows both in the same component.

header.ts

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

@Component({
  selector: 'app-header',
  template: `<h2>Card Header</h2>`
})
export class Header {

  showHeaderMessage() {
    alert('Header method called');
  }
}

product.ts

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

@Component({
  selector: 'app-product',
  template: `
    <p>Laptop - ₹50,000</p>
  `
})
export class Product {

  showProductMessage() {
    alert('Product method called');
  }
}

card.ts

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

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

@Component({
  selector: 'app-card',
  imports: [Header],
  templateUrl: './card.html'
})
export class Card {

  @ViewChild(Header)
  header!: Header;

  @ContentChild(Product)
  product!: Product;

  callHeader() {
    this.header.showHeaderMessage();
  }

  callProduct() {
    this.product.showProductMessage();
  }
}

card.html

<div class="card">

  <app-header></app-header>

  <ng-content></ng-content>

  <button (click)="callHeader()">
    Call Header
  </button>

  <button (click)="callProduct()">
    Call Product
  </button>

</div>

app.ts

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

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

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

app.html

<app-card>

  <app-product></app-product>

</app-card>

Combined Example Explanation

Inside Card itself:

<app-header></app-header>

Therefore:

@ViewChild(Header)
header!: Header;

finds it.

But Product comes from App:

<app-card>

  <app-product></app-product>

</app-card>

and enters Card through:

<ng-content></ng-content>

Therefore:

@ContentChild(Product)
product!: Product;

finds it.

App
 │
 │ provides
 ▼
Product
 │
 │ projection
 ▼
┌────────── Card ──────────┐
│                          │
│ Header                   │
│   ▲                      │
│   │ @ViewChild           │
│                          │
│ <ng-content>             │
│      │                   │
│      └── Product         │
│            ▲             │
│            │             │
│       @ContentChild      │
│                          │
└──────────────────────────┘

Modern Angular APIs

Modern Angular also provides signal-based query functions:

viewChild()
contentChild()

For example:

header = viewChild(Header);

product = contentChild(Product);

Access them using:

this.header()?.showHeaderMessage();

this.product()?.showProductMessage();

The traditional decorator versions are:

@ViewChild(Header)
header!: Header;

@ContentChild(Product)
product!: Product;

Both concepts are important because you will see the decorator APIs extensively in existing Angular applications.


ViewChild vs ContentChild

Feature ViewChild ContentChild
Type View query Content query
Searches Component's own view Projected content
Content created by Component itself Parent/caller
Common relationship Normal template child Projected child
Related to <ng-content> No Yes
Traditional API @ViewChild() @ContentChild()
Modern API viewChild() contentChild()
Multiple version ViewChildren ContentChildren

ViewChildren vs ContentChildren

The same principle applies when querying multiple children.

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

searches for multiple items in the component's own view.

Whereas:

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

searches for multiple items in the component's projected content.

So:

ONE
────────────────────────────
ViewChild     → Own view
ContentChild  → Projected content


MANY
────────────────────────────
ViewChildren    → Own view
ContentChildren → Projected content

Advantages

ViewChild

  • Direct access to a child component.
  • Can access template elements and directives.
  • Useful for calling child methods.
  • Useful for focus, scrolling, and third-party components.

ContentChild

  • Allows reusable container components to interact with projected content.
  • Useful for cards, tabs, dialogs, panels, and custom UI libraries.
  • Works naturally with content projection.

Disadvantages

Both APIs create more direct coupling between components.

For normal communication, prefer:

Parent → Child
      input()

Child → Parent
      output()

Use ViewChild or ContentChild when you genuinely need to query/access a component, directive, or element directly.


Key Points

The most important rule is:

Is the child declared in MY template?
            │
           YES
            ▼
       ViewChild


Was the child passed/projected into me?
            │
           YES
            ▼
      ContentChild

Remember:

ViewChild = my view.
ContentChild = projected content.


Interview Questions & Answers

Q1. What is the difference between ViewChild and ContentChild?

ViewChild queries an element, directive, or component from the component's own template, whereas ContentChild queries something that was projected into the component, usually through <ng-content>.

Q2. When should you use ContentChild?

Use it when a component needs to access content or a component that was supplied by its parent through content projection.

Q3. Is ContentChild related to <ng-content>?

Yes. ContentChild is commonly used to query content that a parent provides to a component and that the component projects using <ng-content>.

Q4. What is the difference between ViewChildren and ContentChildren?

ViewChildren queries multiple matches from the component's own view, while ContentChildren queries multiple matches from projected content.

Q5. What are the modern alternatives?

Modern Angular provides signal-based:

viewChild()
viewChildren()

contentChild()
contentChildren()

The traditional decorator APIs are:

@ViewChild()
@ViewChildren()

@ContentChild()
@ContentChildren()

Interview-Ready Answer

ViewChild is used to access a child component, directive, or element declared in the component's own template. ContentChild is used to access content that is supplied by a parent and projected into the component through <ng-content>. In simple terms, ViewChild searches my own view, while ContentChild searches the content given to me.

 

ContentChild and ContentChildren are different mainly by the number of projected items they retrieve.

ContentChild → gets ONE projected child
ContentChildren → gets MULTIPLE projected children

Main Difference

Feature ContentChild ContentChildren
Number of results One Multiple
Traditional API @ContentChild() @ContentChildren()
Modern API contentChild() contentChildren()
Traditional return Single instance QueryList<T>
Searches Projected content Projected content
Related to <ng-content> <ng-content>

ContentChild — One Projected Component

Parent:

<app-card>

  <app-product></app-product>

</app-card>

Card receives one Product.

@ContentChild(Product)
product!: Product;

Conceptually:

App
 │
 └── Card
      │
      └── Product
           ▲
           │
      @ContentChild

ContentChildren — Multiple Projected Components

Parent:

<app-card>

  <app-product></app-product>

  <app-product></app-product>

  <app-product></app-product>

</app-card>

Now Card receives multiple Products.

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

Conceptually:

App
 │
 └── Card
      │
      ├── Product
      ├── Product
      └── Product
           ▲
           │
    @ContentChildren

You can iterate through them:

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

Easy Way to Remember

                 Projected Content
                        │
          ┌─────────────┴─────────────┐
          │                           │
         ONE                         MANY
          │                           │
          ▼                           ▼
  @ContentChild()             @ContentChildren()
          │                           │
    Single instance              QueryList<T>

The same pattern applies to view queries:

One Multiple
@ViewChild() @ViewChildren()
@ContentChild() @ContentChildren()

Modern Angular

product = contentChild(Product);

One projected child.

products = contentChildren(Product);

Multiple projected children.

Interview-Ready Answer

ContentChild retrieves a single matching item from projected content, while ContentChildren retrieves multiple matching items. With the traditional decorator API, ContentChildren returns a QueryList, whereas ContentChild returns a single matching instance. Both are used to query content projected through a component's content area, commonly associated with <ng-content>.

 

← Back to Articles