48

I want to access the DOM of a component using ViewChild. But when I try to access the nativeElement property, it's undefined.

Below is the snippet.

import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { AlertComponent } from './alert.component';

@Component({
    selector: 'app-root',
    template: `
    <app-alert #alert>My alert</app-alert>
      <button (click)="showAlert()">Show Alert</button>`
})
export class AppComponent implements AfterViewInit {
  @ViewChild('alert') alert;

  showAlert() {
    console.log('alert (showalert)', this.alert.nativeElement);
    this.alert.show();
  }

  ngAfterViewInit() {
    console.log('alert (afterviewinit)', this.alert.nativeElement);
  }
}

Please take a look at the plunk.

Günter Zöchbauer
  • 490,478
  • 163
  • 1,733
  • 1,404
karthikaruna
  • 2,393
  • 5
  • 21
  • 34

1 Answers1

98

If you want to get a reference of an element that hosts a component or directive you need to specify that you want the element instead of the component or directive

@ViewChild('alert', { read: ElementRef }) alert:ElementRef;

See also angular 2 / typescript : get hold of an element in the template

In your case I guess you need two different @ViewChild() one for the component reference to be able to access the show() method, and a 2nd one to be able to access DOM attributes.

Plunker example

Günter Zöchbauer
  • 490,478
  • 163
  • 1,733
  • 1,404
  • Thanks! By default it returns the component instance. How can I explicitly specify the `read` property to return the component instance? Also, it would be great if you can tell what are the other values I can set for different purposes. – karthikaruna Aug 28 '17 at 15:08
  • 3
    If it's a plain HTML element, the default is `ElementRef`, it it hosts a component or directive, you'll get the component instance by default. You can just use the type name of the component or directive to request a specific one like `@ViewChild('alert', { read: AlertComponent }) alert: AlertComponent;` – Günter Zöchbauer Aug 28 '17 at 15:11
  • 3
    Works for `ViewChildren` too – Lahiru Chandima Jul 06 '19 at 13:44
  • 11
    In angular 8, you have to set the static option (which is now mandatory) to false. `@ViewChild('alert', { read: ElementRef, static:false })` Otherwise, it won't work. – alchi baucha Feb 12 '20 at 02:14