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 :)
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 .
The ViewChild decorator returns the first element that matches a given directive, component, or template reference selector.
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.
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.
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.
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 :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With