// Tutorial //

How To Use ViewChild in Angular to Access a Child Component, Directive, or DOM Element

Published on April 27, 2017 · Updated on November 24, 2021
Default avatar
By Alligator.io
Developer and author at DigitalOcean.
How To Use ViewChild in Angular to Access a Child Component, Directive, or DOM Element

Introduction

This article will introduce you to Angular’s ViewChild decorator.

There may be situations where you want to access a directive, child component, or a DOM element from a parent component class. The ViewChild decorator returns the first element that matches a given directive, component, or template reference selector.

Prerequisites

If you would like to follow along with this tutorial:

  • Consider installing @angular/cli.
  • Use @angular/cli to create a new project to test ViewChild functionality in.

This tutorial was verified with @angular/core v13.0.2 and @angular/cli v13.0.3.

Using ViewChild with Directives

ViewChild makes it possible to access directives.

Let’s say you have a SharkDirective. This directive will look for elements with the attribute appShark and prepend the text in the element with the word "Shark".

Ideally, you will use @angular/cli to generate your directive:

  1. ng generate directive shark --skip-tests

This command will create a shark.directive.ts file. And adds the directive to app.module.ts:

app.module.ts
import { SharkDirective } from './shark.directive';
...
@NgModule({
  declarations: [
    AppComponent,
    SharkDirective
  ],
  ...
})

Then, use ElementRef and Renderer2 to rewrite the text. Replace the contents of shark.directive.ts with the following:

shark.directive.ts
import {
  Directive,
  ElementRef,
  Renderer2
} from '@angular/core';

@Directive(
  { selector: '[appShark]' }
)
export class SharkDirective {
  creature = 'Dolphin';

  constructor(elem: ElementRef, renderer: Renderer2) {
    let shark = renderer.createText('Shark ');
    renderer.appendChild(elem.nativeElement, shark);
  }
}

Next, add an appShark attribute to a span containing text in the component template. Replace the contents of app.component.html with the following:

app.component.html
<span appShark>Fin!</span>

When viewing the application in a browser, it will render the word "Shark" before the contents of the element:

Output
Shark Fin!

Now, you can also access the creature instance variable of SharkDirective and set an extraCreature instance variable with its value. Replace the contents of app.component.ts with the following:

app.component.ts
import {
  Component,
  ViewChild,
  AfterViewInit
} from '@angular/core';
import { SharkDirective } from './shark.directive';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
  extraCreature!: string;

  @ViewChild(SharkDirective)
  set appShark(directive: SharkDirective) {
    this.extraCreature = directive.creature;
  };

  ngAfterViewInit() {
    console.log(this.extraCreature); // Dolphin
  }
}

This code used a setter to set the extraCreature variable. Notice that it waits for the AfterViewInit lifecycle hook to access the variable, as this is when child components and directives become available.

When viewing the application in a browser, you will still see the "Shark Fin!" message. However, in the console log, it will display:

Output
Dolphin

The parent component was able to access the value from the directive.

Using ViewChild with DOM Elements

ViewChild makes it possible to access native DOM elements that have a template reference variable.

Let’s say you have an <input> in the template with the #someInput reference variable. Replace the contents of app.component.html with the following:

app.component.html
<input #someInput placeholder="Your favorite sea creature">

Now, you can access the <input> with ViewChild and set the value. Replace the contents of app.component.ts with the following:

app.component.ts
import {
  Component,
  ViewChild,
  AfterViewInit,
  ElementRef
} from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
  @ViewChild('someInput') someInput!: ElementRef;
  ngAfterViewInit() {
    this.someInput.nativeElement.value = 'Whale!';
  }
}

When ngAfterViewInit fires the value of the <input> will be set to:

Output
Whale!

The parent component was able to set the value of the child DOM Element.

Using ViewChild with Child Components

ViewChild makes it possible to access a child component and call methods or access instance variables that are available to the child.

Let’s say you have a PupComponent.

Ideally, you will use @angular/cli to generate your component:

  1. ng generate component pup --flat --skip-tests

This command will create pup.component.ts, pup.component.css, and pup.component.html files. And adds the component to app.module.ts:

app.module.ts
import { PupComponent } from './pup.component';
...
@NgModule({
  declarations: [
    AppComponent,
    PupComponent
  ],
  ...
})

Then, add a whoAmI method to PupComponent which returns a message:

pup.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-pup',
  templateUrl: './pup.component.html',
  styleUrs: ['./pup/component.css']
})
export class PupComponent implements OnInit {

  constructor() { }

  whoAmI() {
    return 'I am a pup component!';
  }

  ngOnInit(): void {
  }

}

Next, reference the child component in the app template. Replace the contents of app.component.html with the following:

app.component.html
<app-pup>pup works!</app-pup>

Now, you can call the whoAmI method from within the parent component class with ViewChild. Replace the contents of app.component.ts with the following:

app.component.ts
import {
  Component,
  ViewChild,
  AfterViewInit
} from '@angular/core';
import { PupComponent } from './pup.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements AfterViewInit {
  @ViewChild(PupComponent) pup!: PupComponent;
  ngAfterViewInit() {
    console.log(this.pup.whoAmI()); // I am a pup component!
  }
}

When viewing the application in a browser, the console log will display:

Output
I am a pup component!

The parent component was able to call the child component’s whoAmI method.

Conclusion

In this tutorial, you used ViewChild to access a directive, child component, and a DOM element from a parent component class.

If the reference changes to a new element dynamically, ViewChild will automatically update its reference.

In cases where you want to access multiple children, you would use ViewChildren instead.

If you’d like to learn more about Angular, check out our Angular topic page for exercises and programming projects.


Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.

Sign up
About the authors
Default avatar
Developer and author at DigitalOcean.

Default avatar
Developer and author at DigitalOcean.

Still looking for an answer?

Was this helpful?
Leave a comment