Question
Angular @ViewChild Returning Undefined: Lifecycle, Child Components, and Fixes
Question
I am learning Angular and trying to access a child component from a parent component using @ViewChild.
In BodyContent.ts I have:
import { ViewChild, Component } from 'angular2/core';
import { FilterTiles } from '../Components/FilterTiles/FilterTiles';
@Component({
selector: 'ico-body-content',
templateUrl: 'App/Pages/Filters/BodyContent/BodyContent.html',
directives: [FilterTiles]
})
export class BodyContent {
@ViewChild(FilterTiles) ft: FilterTiles;
public onClickSidebar() {
console.log(this.ft);
const startingFilter = {
title: 'cognomi',
values: ['griffin', 'simpson']
};
this.ft.tiles.push(startingFilter);
}
}
In FilterTiles.ts:
import { Component } from 'angular2/core';
@Component({
selector: 'ico-filter-tiles',
templateUrl: 'App/Pages/Filters/Components/FilterTiles/FilterTiles.html'
})
export class FilterTiles {
public tiles = [];
constructor() {}
}
BodyContent.html:
<div (click)="onClickSidebar()" class="row" style="height:200px; background-color:red;">
<ico-filter-tiles></ico-filter-tiles>
</div>
FilterTiles.html:
<h1>Tiles loaded</h1>
<div *ngFor="#tile of tiles" class="col-md-4">
... stuff ...
</div>
The FilterTiles.html template is rendered correctly inside the ico-filter-tiles tag, so the child component appears to be loading.
Also, BodyContent is inserted dynamically inside another component using DynamicComponentLoader:
import { Component, DynamicComponentLoader, Injector } from 'angular2/core';
import { Body } from '../../Layout/Dashboard/Body/Body';
import { BodyContent } from './BodyContent/BodyContent';
@Component({
selector: 'filters',
templateUrl: 'App/Pages/Filters/Filters.html',
directives: [Body, Sidebar, Navbar]
})
export class Filters {
constructor(dcl: DynamicComponentLoader, injector: Injector) {
dcl.loadAsRoot(BodyContent, '#ico-bodyContent', injector);
dcl.loadAsRoot(SidebarContent, '#ico-sidebarContent', injector);
}
}
The problem is that when I log this.ft, it is undefined, and trying to access this.ft.tiles throws an error because ft is not set.
Why can @ViewChild be undefined even when the child component is visible, and how should I access a child component correctly in Angular?
Short Answer
By the end of this page, you will understand what @ViewChild does, why it may be undefined, and when Angular actually makes a child component available. You will also learn the role of lifecycle hooks like ngAfterViewInit, how view queries relate to the component template, and safer ways to communicate between parent and child components.
Concept
@ViewChild lets a parent component get a reference to something inside its own view, usually a child component, directive, or DOM element.
In Angular, this reference is not guaranteed to exist immediately when the class is created. Angular first:
- Creates the parent component
- Builds its template
- Creates child components inside that template
- Resolves
@ViewChild - Runs lifecycle hooks such as
ngAfterViewInit
That means @ViewChild is tied to the view lifecycle, not just the fact that some HTML is visible on screen.
A common beginner mistake is to assume:
- if the child component is rendered,
- then
@ViewChildmust already be available everywhere.
But Angular only sets the @ViewChild property after the view has been initialized.
This matters because parent components often try to use a child reference too early:
- in the constructor
- in
ngOnInitin older Angular behavior - during some event that fires before the query is ready
- when the child belongs to a different dynamically loaded component tree
In your example, the core idea is: FilterTiles is part of BodyContent's view, so can query it with . But the query only becomes reliable after Angular finishes creating that view.
Mental Model
Think of a parent component as a manager setting up a room.
- The manager arrives first.
- The furniture is brought in afterward.
- Only once the furniture is placed can the manager point to a chair and say, “Use that one.”
@ViewChild is the manager pointing to a specific piece of furniture in the room.
If the manager tries to point to the chair before the room is fully set up, the result is undefined.
In Angular terms:
- the parent component instance is created first
- the child component instance is created later as part of the template
@ViewChildgets filled in only after Angular finishes assembling the view
So the mental rule is:
If you need a child from @ViewChild, wait until the view exists.
Syntax and Examples
The basic syntax for querying a child component is:
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { ChildComponent } from './child.component';
@Component({
selector: 'app-parent',
template: `<app-child></app-child>`
})
export class ParentComponent implements AfterViewInit {
@ViewChild(ChildComponent) child!: ChildComponent;
ngAfterViewInit() {
console.log(this.child);
}
}
Example: calling a child method
import { Component, ViewChild, AfterViewInit } from '@angular/core';
@Component({
selector: 'app-child',
:
})
{
message = ;
() {
.();
}
}
({
: ,
:
})
{
() child!: ;
() {
.(, ..);
}
() {
(.) {
..();
}
}
}
Step by Step Execution
Consider this simplified example:
@Component({
selector: 'app-parent',
template: `
<button (click)="addItem()">Add</button>
<app-child></app-child>
`
})
export class ParentComponent implements AfterViewInit {
@ViewChild(ChildComponent) child: ChildComponent;
ngAfterViewInit() {
console.log('after view init', this.child);
}
addItem() {
console.log('button clicked');
console.log(this.child);
}
}
Here is what happens step by step:
- Angular creates
ParentComponent. - At this moment, the
childproperty exists as a class field, but Angular may not have assigned the real child instance yet. - Angular reads the parent template.
- Angular sees
<app-child></app-child>and creates .
Real World Use Cases
@ViewChild is useful when the parent needs direct access to a child component or element.
Common practical uses
-
Triggering a child method
- Example: a parent button calls
child.resetForm().
- Example: a parent button calls
-
Reading child state
- Example: a parent checks whether a custom form component is valid.
-
Working with DOM elements
- Example: focusing an input after a dialog opens.
-
Using third-party widgets
- Example: getting a chart or editor instance after it renders.
-
Layout or measurement logic
- Example: reading element height after the page has been drawn.
Example in an app
A search page may have:
SearchPageComponentas parentFilterPanelComponentas childResultsGridComponentas another child
The parent may use @ViewChild(FilterPanelComponent) to reset all filters when the user clicks “Clear all”.
Important note
Real Codebase Usage
In real Angular projects, developers use @ViewChild carefully and usually combine it with clearer component communication patterns.
Common patterns
1. Parent calls a child method deliberately
@ViewChild(FilterTiles) filterTiles!: FilterTiles;
clearFilters() {
this.filterTiles.clear();
}
This is common when the child exposes a small public API.
2. Guard clauses before use
if (!this.filterTiles) {
return;
}
This avoids runtime errors when the child is not available yet.
3. Prefer @Input() for data flow
Instead of doing this:
this.ft.tiles.push(startingFilter);
many codebases prefer this:
<ico-filter-tiles [tiles]=></ico-filter-tiles>
Common Mistakes
1. Using @ViewChild too early
Broken example:
constructor() {
console.log(this.ft); // undefined
}
Why it fails:
- The constructor runs before Angular finishes building the view.
Fix:
- Use
ngAfterViewInit().
ngAfterViewInit() {
console.log(this.ft);
}
2. Assuming visible HTML means the query is ready
Seeing a child component on screen does not mean the query was available at every earlier line of code.
Fix:
- Think in lifecycle order, not just visual output.
3. Querying something that is not in the component's own view
@ViewChild only searches inside that component’s template.
Broken idea:
- Trying to access a component that belongs to another component tree.
Comparisons
| Concept | Best for | When to use | Notes |
|---|---|---|---|
@ViewChild | Accessing a child instance directly | Calling child methods, reading element/component references | Available after view init |
@Input() | Passing data from parent to child | Parent owns data and sends it down | Preferred for normal data flow |
@Output() | Sending events from child to parent | Child needs to notify parent about actions | Good for loose coupling |
| Shared service | Sharing state across unrelated components | Multiple components need common data | Useful beyond direct parent-child communication |
@ViewChild vs @Input()
Cheat Sheet
@ViewChild(ChildComponent) child: ChildComponent;
Rules
@ViewChildlooks inside the component's own template.- The child reference is available after the view is initialized.
- Use
ngAfterViewInit()for setup that depends on the child. - If the child is conditionally rendered, the query may be
undefined. - Prefer
@Input()for normal parent-to-child data passing.
Safe pattern
import { Component, ViewChild, AfterViewInit } from '@angular/core';
export class ParentComponent implements AfterViewInit {
@ViewChild(ChildComponent) child!: ChildComponent;
ngAfterViewInit() {
console.log(this.child);
}
() {
(!.) ;
..();
}
}
FAQ
Why is @ViewChild undefined in Angular?
Because Angular has not finished creating the view yet, or because the queried child does not currently exist in the parent’s template.
When is @ViewChild available?
It is reliably available after Angular initializes the view, typically in ngAfterViewInit().
Can I use @ViewChild in the constructor?
No. The constructor runs too early. The view and its children do not exist yet.
Why is the child visible on screen but @ViewChild is still a problem?
Visibility alone does not tell you when the query became available. Angular assigns view queries as part of the component lifecycle.
Should I use @ViewChild to pass data to a child component?
Usually no. @Input() is the preferred way to pass data from parent to child.
What happens if the child is inside *ngIf?
If the condition is false, the child is not created, so @ViewChild will be undefined.
Is dynamic component loading related to this issue?
It can be. Dynamically loaded components still follow lifecycle timing. If you query a child before the dynamic view is fully initialized, the reference may not be ready.
Mini Project
Description
Build a small parent-child Angular example where a parent adds filter items to a child component. This project demonstrates when @ViewChild becomes available and how to safely use it without causing undefined errors.
Goal
Create a parent component that accesses a child component with @ViewChild and adds items only after the child view is ready.
Requirements
- Create a child component with a
tilesarray and a method to add a tile. - Render the child component inside a parent component template.
- Use
@ViewChildin the parent to access the child instance. - Use
ngAfterViewInit()to verify the child is available. - Add a button that safely sends a tile from the parent to the child.
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.
Angular Dependency Injection: Fix "Can't Resolve All Parameters for Component" Errors
Learn why Angular shows "Can't resolve all parameters for component" and how to fix service injection issues in components.