Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@ViewChild returns undefined

Tags:

For some reason my @ViewChild in my Angular 5 App does not work. I have defined it like this in my component:

case-detail.component.html:

<div class="inner-tab-content" #innerTabContent>     <!-- // more content here --> </div> 

I have implemented @ViewChild in my controller (above the constructor) like this:

case-detail.component.ts

@ViewChild('innerTabContent') tabContentElement: ElementRef; 

And I want to access it here in the component: case-detail.component.ts

ngAfterViewInit() {     console.log("scroll top: " + this.tabContentElement.nativeElement); } 

I've implemented the AfterViewInit interface. ngAfterViewInit() is called correctly. However, this.tabContentElement is always undefined.

Any help is greatly appreciated :)

like image 521
dave0688 Avatar asked Jan 18 '18 12:01

dave0688


People also ask

Why is ViewChild returning undefined?

The problem can be caused by the *ngIf or other directive. The solution is to use the @ViewChildren instead of @ViewChild and subscribe the changes subscription that is executed when the component is ready. For example, if in the parent component ParentComponent you want to access the child component MyComponent .

What does ViewChild return?

The ViewChild decorator returns the first element that matches a given directive, component, or template reference selector.

Why do we use @ViewChild in angular2?

Conclusion. The @ViewChild decorator allows us to inject into a component class references to elements used inside its template, that's what we should use it for. Using @ViewChild we can easily inject components, directives or plain DOM elements.

What is the difference between @ViewChild and @input?

While Angular inputs/outputs should be used when sharing data to and from child components, ViewChild should be used when trying to utilize properties and methods of the child component directly in the parent component.


1 Answers

ViewChild() works fine on latest plunker Angular version with the scenario you describe.

Demonstration in this plunker : https://plnkr.co /edit/KzWnkE5Hvp7NUow6YAxy

EDIT: Here is a replacement StackBlitz for the above Plunker: https://stackblitz.com/edit/angular-ivy-pzaglm

component :

ngAfterViewInit() {     console.log(this.testView); // correctly outputs the element in console, not undefined } 
  • Check that ElementRef and ViewChild are correctly imported from '@angular/core'

  • Your element might simply not be there at the time of AfterViewInit (in case there is a *ngIf, for instance. (seems the case as per your comments)

In the latter case, you can use a wrapper element and ViewChildren , that emits some event when a new child element is added - more info on documentation here : https://angular.io/api/core/ViewChildren

note that there might be some issue with native div as per this question : @ViewChildren does not get updated with dynamically added DOM elements , but this can be worked around by using a new component that wraps your div, for instance.

EDIT

Or you can also use a timeout to wait for the component to be rendered. I must say that I find this solution 'dirty', but glad it works for you :)

like image 169
Pac0 Avatar answered Sep 27 '22 18:09

Pac0