ViewChild and ContentChild
ViewChild gives parent access to its child components and DOM elements. ContentChild gives access to projected content. New signal-based APIs make both simpler.
ViewChild is a decorator (and now a function) that gives a parent component access to its children โ child components, directives, or DOM elements.
"ViewChild = CCTV camera โ parent se child ko dekho aur control karo."
Use cases:
- Call a child component's public method
- Read a child component's public property
- Access a DOM element (input focus, scroll position)
- Access a directive's API
Two APIs: Old @ViewChild() decorator (always worked) and new viewChild() signal function (Angular 17+). Both work, but the signal version is cleaner.
ViewChild vs ContentChild โ key difference:
- ViewChild โ looks INSIDE the component's own template
- ContentChild โ looks at content PROJECTED from parent via ng-content
Access a child component to call its methods or read its properties.
import { Component, ViewChild, AfterViewInit } from '@angular/core';
@Component({...})
export class ChildComponent {
greet(name: string) {
return `Hello ${name} from child!`;
}
get status() {
return 'Child is ready ๐';
}
}
// PARENT
@Component({...})
export class ParentComponent implements AfterViewInit {
@ViewChild(ChildComponent) childComp!: ChildComponent;
ngAfterViewInit() {
// ViewChild is only available AFTER view init!
console.log(this.childComp.status); // 'Child is ready ๐'
console.log(this.childComp.greet('Bhai')); // 'Hello Bhai from child!'
}
callChildMethod() {
this.childComp.greet('User');
}
}
"Child ke public methods call karo โ parent se remote control."
IMPORTANT timing rules:
ngAfterViewInitโ first time ViewChild is available- In
constructorโ undefined (component not created yet) - In
ngOnInitโ undefined (view not initialized yet) ngAfterViewCheckedโ available and updated
Reference by template variable:
// Template: <app-child #theChild>
@ViewChild('theChild') childComp!: ChildComponent;
// Same result, accessed by template variable nameAccess DOM elements directly with ViewChild.
import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
@Component({
template: `
<input #searchInput type="text" placeholder="Search biryanis...">
<button (click)="focusInput()">Focus</button>
<div #scrollContainer class="scroll-box">
@for (item of items; track $index) {
<p>{{ item }}</p>
}
</div>
`
})
export class SearchComponent implements AfterViewInit {
@ViewChild('searchInput') searchInput!: ElementRef<HTMLInputElement>;
@ViewChild('scrollContainer') scrollContainer!: ElementRef<HTMLDivElement>;
ngAfterViewInit() {
this.searchInput.nativeElement.focus(); // Auto-focus on load
}
focusInput() {
this.searchInput.nativeElement.focus();
this.searchInput.nativeElement.value = 'Biryani';
}
scrollToTop() {
this.scrollContainer.nativeElement.scrollTop = 0;
}
}
"DOM element ko naam do (#myInput), ViewChild se access karo."
โ ๏ธ SSR warning: nativeElement doesn't exist on the server. For SSR-safe code, use Renderer2 or check if platform is browser:
import { isPlatformBrowser } from '@angular/common';
import { PLATFORM_ID, inject } from '@angular/core';
const platformId = inject(PLATFORM_ID);
if (isPlatformBrowser(platformId)) {
this.searchInput.nativeElement.focus();
}ContentChild accesses content that the parent projects into the child via ng-content.
// CHILD COMPONENT
@Component({
selector: 'app-card',
template: `
<div class="card">
<div class="header">
<ng-content select="[header]"></ng-content>
</div>
<div class="body">
<ng-content></ng-content>
</div>
</div>
`
})
export class CardComponent {
@ContentChild('headerTpl') headerTpl!: TemplateRef<any>;
@ContentChildren(TabComponent) tabs!: QueryList<TabComponent>;
ngAfterContentInit() {
console.log('Tabs count:', this.tabs.length);
}
}
// PARENT TEMPLATE
<app-card>
<ng-template #headerTpl>
<h2>๐ฅ Special Biryani</h2>
</ng-template>
<p>This is the main content projected via ng-content.</p>
</app-card>
"ContentChild = ng-content ke andar ka content access karo."
ViewChild vs ContentChild timing:
- ViewChild available in
ngAfterViewInit - ContentChild available in
ngAfterContentInit - ContentChildren always INIT before ViewChildren
@ContentChildren (plural) gets ALL matching content children as a QueryList that updates dynamically.
Angular 17+ introduced signal-based versions of ViewChild and ContentChild.
import { Component, viewChild, contentChild } from '@angular/core';
@Component({...})
export class ParentComponent {
// NEW: viewChild() returns a Signal
child = viewChild(ChildComponent);
searchInput = viewChild<ElementRef<HTMLInputElement>>('searchInput');
headerTpl = contentChild<TemplateRef<any>>('headerTpl');
// Read the value โ just call it like any signal!
ngAfterViewInit() {
// OLD: this.childComp.greet('User');
// NEW:
this.child()?.greet('User');
this.searchInput()?.nativeElement.focus();
}
// In template โ can use directly!
// {{ child()?.status }}
// {{ headerTpl() }}
}
"viewChild() = ViewChild ka signal version โ modern aur clean."
Benefits over decorator version:
- No
AfterViewInitlifecycle hook required - Value is a Signal โ can be used in computed(), effect()
- Auto-updates when child is conditionally shown/hidden (@if)
- No
!non-null assertion needed - Template can read it directly:
{{ child()?.status }}
Comparison:
// OLD โ @ViewChild decorator
@ViewChild(ChildComponent) child!: ChildComponent;
// Need AfterViewInit to use it
// NEW โ viewChild() signal
child = viewChild(ChildComponent);
// Use child() anywhere โ signal ecosystemKey Takeaways
- โ ViewChild = access child components, DOM elements from parent
- โ Available in ngAfterViewInit โ NOT in constructor or ngOnInit
- โ ContentChild = access projected content from parent (ng-content)
- โ viewChild() signal (new) โ no lifecycle hook needed, signal-powered
- โ contentChild() signal (new) โ same benefits for projected content
- โ nativeElement breaks SSR โ use Renderer2 or isPlatformBrowser check
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login