ViewChild vs ContentChild in Angular
The main difference is where Angular searches.
ViewChildsearches inside the component's own template.ContentChildsearches 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
ViewChildis used to access a child component, directive, or element declared in the component's own template.ContentChildis used to access content that is supplied by a parent and projected into the component through<ng-content>. In simple terms,ViewChildsearches my own view, whileContentChildsearches the content given to me.
ContentChild and ContentChildren are different mainly by the number of projected items they retrieve.
ContentChild→ gets ONE projected childContentChildren→ 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
ContentChildretrieves a single matching item from projected content, whileContentChildrenretrieves multiple matching items. With the traditional decorator API,ContentChildrenreturns aQueryList, whereasContentChildreturns a single matching instance. Both are used to query content projected through a component's content area, commonly associated with<ng-content>.