When working with Angular 2, it’s common to encounter scenarios where you need to access a child component from a parent component using the @ViewChild decorator. However, you might sometimes find that @ViewChild returns undefined or null, which can be confusing, especially if you’re new to Angular. This issue often arises due to the timing of Angular’s lifecycle hooks and the use of directives like *ngIf. In this article, we’ll dive deep into the problem, explore why it happens, and discuss multiple solutions to ensure @ViewChild works as expected.

The Problem: @ViewChild Returning undefined or null

Let’s consider the following example where you have a parent component (BodyContent) that needs to access a child component (FilterTiles) using @ViewChild:
example1

Here, @ViewChild is used to reference the FilterTiles component. However, developers might find that ft is undefined when accessed. This can be due to the following reasons:

  1. Lifecycle Hook Timing: The @ViewChild reference is populated only after Angular has fully initialized the component’s view. If you try to access it in the constructor or ngOnInit, it might still be undefined.
  2. Use of *ngIf: If the child component is conditionally rendered with *ngIf, it might not exist in the DOM when @ViewChild is queried, resulting in null.

Solution 1: Using ngAfterViewInit Lifecycle Hook

To ensure that @ViewChild is correctly initialized, you should use the ngAfterViewInit lifecycle hook. This hook is called after Angular has fully initialized the component’s view, making it the ideal place to access @ViewChild.

example-2

By using ngAfterViewInit, you ensure that Angular has finished rendering the view, and @ViewChild should now correctly reference the child component.

Solution 2: Dealing with *ngIf Using @ViewChildren

A common scenario where @ViewChild returns null is when the child component is wrapped in an *ngIf directive. The *ngIf directive removes the component from the DOM if its condition is false, so @ViewChild can’t find it.
Here’s an example:
example-3

In this case, @ViewChildren is used instead of @ViewChild. @ViewChildren returns a QueryList that updates dynamically as the DOM changes. By subscribing to the changes observable, you can ensure that you always have access to the most up-to-date list of components, even if they are conditionally rendered with *ngIf.

To Summarize

  • ngAfterViewInit Lifecycle Hook: Always use ngAfterViewInit to access @ViewChild to ensure the view is fully initialized.
  • Handling *ngIf with @ViewChildren: If you’re using *ngIf, consider using @ViewChildren and subscribe to changes for a dynamic and responsive solution.
  • Understanding Angular Timing: Be aware of how Angular’s lifecycle hooks and directives like *ngIf interacts to ensure your components are initialized and accessible when needed.

By following these best practices, you can avoid common pitfalls with @ViewChild and ensure your Angular components interact seamlessly.

Support On Demand!

Angular