Reach Into Your Template — Or Your Projected Content
viewChild() & contentChild()
viewChild reads an element or component in your own template; contentChild reads something a parent projected into you.
What you'll learn
- Read with viewChild and viewChildren signals
- Read projected content with contentChild
- Use the required variant for guaranteed presence
Most of the time you bind data with property and event binding. Occasionally you need to imperatively grab a DOM element or a child component — that is what query functions are for.
viewChild — Your Own Template
import { Component, ElementRef, viewChild } from '@angular/core';
@Component({
selector: 'app-login',
standalone: true,
template: `<input #emailRef /><button (click)="focus()">Focus</button>`,
})
export class LoginComponent {
email = viewChild<ElementRef<HTMLInputElement>>('emailRef');
focus() {
this.email()?.nativeElement.focus();
}
} viewChild() returns a signal. Call it to read; it is undefined until the view has rendered.
Required Variant
If you know the element will always exist, skip the null check.
email = viewChild.required<ElementRef<HTMLInputElement>>('emailRef');
// this.email().nativeElement — no optional chain needed viewChildren — Multiple Matches
import { viewChildren } from '@angular/core';
import { TabComponent } from './tab.component';
tabs = viewChildren(TabComponent);
activateFirst() {
this.tabs()[0]?.activate();
} viewChildren returns a signal of an array, recomputed whenever the matching set changes.
contentChild — Projected Content
contentChild reads markup the parent projected via ng-content.
import { Component, contentChild } from '@angular/core';
@Component({
selector: 'app-card',
standalone: true,
template: `<ng-content />`,
})
export class CardComponent {
header = contentChild<ElementRef>('header');
} The parent passes <div #header>Title</div> inside <app-card>, and the card can read it.