Tutorial

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

Angular

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.

Using ViewChild with Directives

ViewChild makes it possible to access directives.

Let’s say we have a SharkDirective.

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

  • ng generate directive shark

Otherwise, you may need to manually add it to app.module.ts:

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

Our directive will look for elements with the attribute appShark and prepend the text in the element with the word Shark:

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, we will add a Shark to Fin by using it in the component template:

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

When viewing the application in a browser, it will display as:

Output
Shark Fin!

Now, we can access the creature instance variable of SharkDirective and set an extraCreature instance variable with its value:

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
  }
}

We used a setter here to set the extraCreature variable. Notice that we wait for the AfterViewInit lifecycle hook to access our variable, as this is when child components and directives become available.

When viewing the application in a browser, we 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 we have an <input> in our template with the #someInput reference variable:

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

Now, we can access the <input> with ViewChild and set the value:

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 our <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 we have a ChildComponent. Ideally, you will use @angular/cli to generate your component:

  • ng generate component child --flat

Otherwise, you may need to create child.component.css and child.component.html files and manually add it to app.module.ts:

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

We will add a whoAmI method to ChildComponent which returns a message:

child.component.ts
whoAmI() {
  return 'I am a child component!';
}

Next, we will reference the component in our app template:

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

Now, we can call the whoAmI method from within our parent component class with ViewChild like this:

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

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

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

Output
I am a child component!

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

Conclusion

You have learned to use 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’d want to access multiple children, you’d use ViewChildren instead.

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

0 Comments

Creative Commons License