Tutorial

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

Updated on November 24, 2021
authorauthor

Alligator.io and Bradley Kouchi

English
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.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Alligator.io

author



Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.