Use viewChild or viewChildren to query elements declared in a component’s own template; use contentChild or contentChildren to query content projected into it. Each query returns a signal, so read its current value by calling it, such as this.header(). Signal queries are production-ready in Angular 19 and later, and Angular recommends them for new projects.
Choose the query by where the child comes from
A view query looks inside the component’s own template. A content query looks for content supplied between the component’s opening and closing tags where it is used. Queries do not cross component boundaries, so a parent cannot use a query to reach through a child component and inspect that child’s internal template.
As an Amazon Associate I earn from qualifying purchases.
| Query | Searches | Result |
|---|---|---|
viewChild |
The component’s own template | One match or undefined |
viewChildren |
The component’s own template | An array of matches |
contentChild |
Content projected into the component | One match or undefined |
contentChildren |
Content projected into the component | An array of matches |
Choose a singular query when you expect at most one matching element or component; choose a plural query when you need every match. Angular’s query guide explains the distinctions and available options.
Query an element in the component’s own template
Import the query function and declare it as a class-field initializer in the component or directive. Query functions are compiler-recognized APIs: do not call them as ordinary functions inside a constructor or method.
#1 Best Overall
import { Component, computed, viewChild } from '@angular/core';
import { HeaderComponent } from './header.component';
@Component({
selector: 'app-page',
template: '<app-header />'
})
export class PageComponent {
header = viewChild(HeaderComponent);
headerText = computed(() => this.header()?.text);
}
Because the target may not exist, the inferred value of header() can be undefined. Use optional chaining when absence is valid, as in this.header()?.text. The computed value updates reactively as the query result changes.
Query multiple matches
Use viewChildren when the template can contain several instances. It returns an array, which can be transformed in a computed signal:
Rank #2
import { Component, computed, viewChildren } from '@angular/core';
import { ActionComponent } from './action.component';
@Component({
selector: 'app-toolbar',
template: '<app-action /><app-action />'
})
export class ToolbarComponent {
actions = viewChildren(ActionComponent);
labels = computed(() => this.actions().map(action => action.label));
}
Query projected content
Use a content query when the matching child is provided by the component’s caller rather than declared in the component’s own view. For example, a component can query a toggle passed into its content:
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →import { Component, contentChild } from '@angular/core';
import { ToggleComponent } from './toggle.component';
@Component({
selector: 'app-panel',
template: '<ng-content />'
})
export class PanelComponent {
toggle = contentChild(ToggleComponent);
}
The caller can then supply the child in the panel’s content. As with a singular view query, toggle() may be undefined, so handle absence unless the component contract guarantees a match.
Rank #3
Understand content-query traversal
contentChild searches descendants by default. contentChildren searches only direct children by default; set its descendants option when deeper descendants in the same template should match. This option does not let a query cross a component boundary.
Handle conditional and required targets
Angular keeps query results current as the template changes. A singular query can become undefined when its target is absent, including when an @if condition removes it. Code that reads an optional query should therefore account for the target appearing or disappearing rather than assuming it is permanently available.
Rank #4
When a match is guaranteed by the component’s template or usage contract, viewChild.required and contentChild.required express that requirement. They report an error if no match exists and their result types exclude undefined. Do not use a required query if conditional rendering or caller-provided content can legitimately omit the target. See the viewChild API reference for the required-query API.
Use signal queries in the right Angular version
Angular’s migration guide says the improved query APIs are production-ready as of v19.0, and the current API reference marks viewChild stable since v19.0. The archived Angular v18 guide labels signal queries developer preview; that earlier label should not be applied to v19 and later.
Signal queries make results directly composable with signal-based logic such as computed and effect. Plural signal queries expose standard arrays rather than decorator-query QueryList values. Angular also cites more predictable timing and improved type inference among the benefits. Existing decorator-based queries remain supported; Angular’s current guide says, “While the Angular team recommends using the signal-based query function for new projects, the original decorator-based query APIs remain fully supported.”
Migrate existing decorator queries
For an existing project, Angular provides an automated migration and a VS Code code-refactor action. The command is:
ng generate @angular/core:signal-queries-migration
Review the generated changes in the context of the project’s Angular version. In particular, verify that required-query conversions reflect actual guarantees in the template or component contract. The official migration guide documents the migration options.
Check the query before debugging its value
- Confirm that you chose a view query for the component’s own template or a content query for projected content.
- Confirm the target is not hidden by control flow such as
@ifat the moment you read the signal. - For content queries, check whether the default traversal depth matches the target’s position.
- Check component boundaries: a query cannot inspect another component’s private view.
- Call the query signal, for example
this.header(), rather than treating the field itself as the queried instance.
Angular’s signal-query tutorial demonstrates the core pattern in a guided example.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




