Signals

Angular @ViewChild: In-Depth Explanation (All Features Covered)

The Angular @ViewChild decorator is one of the first decorators that you will run into while learning Angular, as it's also one of the most commonly used decorators. This decorator has a lot of features: some of them might not be very well known but they are extremely useful. In this post, we are go

Angular @ViewChild: In-Depth Explanation (All Features Covered) — Signals article by Angular University on Angular In Depth
Angular @ViewChild: In-Depth Explanation (All Features Covered) — Signals article by Angular University on Angular In Depth
On this page · 12 sections

The @ViewChild decorator is typically among the first Angular features developers encounter, and it remains one of the most frequently used decorators in the framework.

Despite its popularity, this decorator includes a number of capabilities that are not widely known, yet they can be remarkably practical.

This guide will walk through every feature available with this decorator, offering concrete examples for each scenario to illustrate how they work in practice.

It's worth noting that a signal-based alternative to this decorator now exists: the viewChild() signal query. You can explore that topic in detail here:

Angular Signal Queries: viewChild, contentChild, viewChildren, contentChildren (Complete Guide)

Outline of Topics

Below is a summary of what will be discussed in this post:

  • When is the @ViewChild decorator necessary?
  • Understanding the AfterViewInit Lifecycle Hook
  • Defining the scope of @ViewChild template queries
  • Injecting a component with @ViewChild
  • Injecting a standard HTML element using @ViewChild
  • Injecting the underlying HTML element of a component
  • Injecting one of the multiple directives associated with an element or component
  • Code Samples (GitHub Repository)
  • Conclusion

With that roadmap set, let's dive right into the @ViewChild decorator.

When is @ViewChild required?

In Angular, a component's template is built by combining ordinary HTML tags with other Angular components.

For instance, consider the AppComponent template below, which integrates both standard HTML and custom components:

This template contains a variety of element types, such as:

  • standard HTML tags like h2 and div
  • custom application components, for example the <color-sample> component
  • third-party components, such as a color picker
  • multiple Angular Material components as well

Here’s how the AppComponent renders on screen:

Sample Application for trying out view child

All the examples in this guide will be based on this initial template. The <color-sample> component appears as the small blue palette square, and next to it is an input connected to a color picker popup.

Why use the @ViewChild decorator?

Often, it's possible to coordinate the various components and HTML elements directly within the template using template references like #primaryInput or #primaryColorSample, without involving the AppComponent class.

However, this isn't always sufficient. There are instances where the AppComponent does require references to the elements within its own template to manage interactions between them.

In such cases, we can query the template to obtain references to those elements and have them injected into the AppComponent class—this is precisely the purpose of @ViewChild.

Injecting a reference to a component with @ViewChild

Suppose AppComponent needs a reference to the <color-sample> component used in its template to invoke a method directly on it.

To achieve this, we can use @ViewChild to inject a reference to the <color-sample> instance, identified by the template reference #primaryColorSample:

With @ViewChild, the primarySampleComponent member variable will be populated by Angular with a ColorSampleComponent instance.

This instance is the exact same one linked to the <color-sample> custom element present in the template.

When do variables injected via @ViewChild become available?

It's important to note that the injected member variable is not immediately accessible when the component is constructed!

Angular populates this property automatically, but only later in the component lifecycle, specifically after the view has finished initializing.

The AfterViewInit Lifecycle Hook

To write initialization code that relies on references injected by @ViewChild, such code should be placed within the AfterViewInit lifecycle hook.

Here's an example demonstrating how to use this hook:

When running this program, the console output is as follows:

View Child base use case

As shown, Angular automatically populates our member variable primaryColorSample with a reference to the component.

Is ngOnInit() a viable alternative to ngAfterViewInit()?

To guarantee that the references provided by @ViewChild are available, initialization logic should always be placed in ngAfterViewInit().

Although the template references might be available during ngOnInit() in some situations, relying on that is not recommended.

Scope of @ViewChild template queries

The @ViewChild decorator allows the injection of any component, directive, or HTML element located in a component's template into that same component.

However, how deep down the component tree can queries reach? Let's attempt to use @ViewChild to fetch a component nested further within the tree.

For example, let's examine the structure of the <color-sample> component:

This component internally uses the <mat-icon> component to render the small palette icon.

Let's see if we can query that <mat-icon> component and inject it directly into AppComponent:

Upon running this, the console shows the following:

View Child cannot cross component boundaries

As observed in the console output:

The @ViewChild decorator cannot access elements across component boundaries!

Visibility scope of @ViewChild template queries

This implies that queries with @ViewChild can only see elements within the component's own template. It's crucial to understand that @ViewChild cannot be used to inject:

  • Anything from the templates of child components
  • Nor anything from the templates of parent components

In summary, the @ViewChild decorator serves as a template querying mechanism that is local to the individual component.

That covers the most typical use of @ViewChild, but there's much more to explore. Let's look at some additional use cases.

Injecting a reference to a DOM element with @ViewChild

Sometimes, instead of injecting a child component, you may want to directly interact with a plain HTML element in the template, like the h2 title tag in AppComponent.

To do this, first assign a template reference to the HTML tag you wish to inject:

As shown, we've assigned the #title template reference to the h2 tag. Now, we can have the h2 element injected directly into our component class like so:

Notice that we pass the string 'title' to the @ViewChild decorator, which matches the name of the template reference on the h2 tag.

Since h2 is a plain HTML element, and not an Angular component, we get an ElementRef wrapping the native DOM element:

Angular ViewChild example of injection of plain HTML elements

ElementRef is a wrapper around the native DOM element, accessible via the nativeElement property.

By accessing nativeElement, we can perform any native DOM operations on the h2 tag, such as addEventListener().

This demonstrates using @ViewChild to interact with standard HTML elements. But what if we need the DOM element associated with an Angular component instead?

After all, the <color-sample> HTML tag is a DOM element, even though it has a ColorSampleComponent instance attached to it.

Injecting the DOM element of a component with @ViewChild

Let's illustrate this with an example. Consider the <color-sample> component inside AppComponent:

The <color-sample> component is given a template reference #primaryColorSample.

What happens if we try to use this template reference to inject the <color-sample> DOM element, as we did with the h2 tag?

Surprisingly, running this program shows that we do not get the native DOM element this time:

Angular ViewChild example

Default behavior of @ViewChild injection by template reference

Instead, we receive the ColorSampleComponent instance! This is indeed the default behavior of @ViewChild when injecting by template reference name:

  • a reference on a component yields the component instance

  • a reference on a plain HTML element yields the wrapped DOM element

The @ViewChild options argument

But in our case, we want the DOM element linked to the component. This remains possible by using the second argument of the @ViewChild decorator:

Here, we pass a second argument containing a configuration object with the read property set to ElementRef.

The read property defines exactly what should be injected when multiple injectables might be available.

By setting read to ElementRef, we're explicitly asking for the DOM element (wrapped in ElementRef) of the matched template reference, rather than the component.

Running the program now yields the following result:

Angular ViewChild example

Let's explore another scenario where the read property proves beneficial.

Injecting one of several directives with @ViewChild

As your application grows with more directives and libraries, the need for the read property often becomes more frequent.

For instance, returning to the color picker example, let's try to open the color picker when the color sample is clicked:

This example attempts to integrate components using only template references.

The click on <color-sample> is detected, and then the #primaryInput reference is used to access the colorPicker directive and open the dialog.

Using template references is often effective, but not in this particular case!

Here, the template reference #primaryInput points to the <input> DOM element, and not to the colorPicker directive applied to that element.

If you run this version, you'll encounter the following error:

Angular ViewChild example

This error arises because, by default, the template reference primaryInput refers to the input box DOM element rather than the colorPicker directive.

Injecting Directives using @ViewChild

Clearly, this isn't the right way to obtain a reference to a directive, especially when multiple directives are applied to the same HTML element or component.

To resolve this, let's first modify the template to delegate the click event handling to the AppComponent class:

Then, in the AppComponent class, we inject the color picker directive as follows:

Now we have a correct reference to the colorPicker directive!

Clicking the small palette icon will now open the color picker as expected:

ViewChild sample application

With this final example, we've covered all the features of the @ViewChild operator and their typical use cases. Let's summarize what we've learned.

Code Samples (GitHub Repository)

All the runnable code from these examples is available in the following GitHub repository.

Conclusion

The @ViewChild decorator enables the injection of references to elements within a component's template directly into the component class—that is its primary function.

With @ViewChild, we can easily inject components, directives, or standard DOM elements. The decorator also allows overriding its defaults to specify precisely what should be injected when multiple options exist.

@ViewChild serves as a local template querying mechanism that cannot see into the internals of child components.

By injecting references into the component class, we can easily implement coordination logic involving multiple template elements.

Why @ViewChild isn't always necessary

Remember, there are many cases where this decorator isn't strictly needed. Simple interactions can often be handled directly in the template using template references, bypassing the component class altogether.

I hope this post helps clarify @ViewChild, and I trust you found it useful!

For those interested in exploring more advanced Angular Core features like @ViewChild, we suggest checking out the Angular Core Deep Dive course, which covers Angular core in greater depth.

If you have any questions or comments, please share them below, and I'll respond promptly.

To stay updated on future posts about Angular Universal and other Angular topics, feel free to subscribe to our newsletter:

If you're new to Angular, consider taking a look at the Angular for Beginners Course:

Angular @ViewChild: In-Depth Explanation (All Features Covered) — figure 9
AU
Angular University

Writes about RxJS, Components, Signals. Active 2015–2026.

All 79 articles →