ViewChild is undefined in angular 13
Asked Answered
D

3

6

I am trying to call view child of a child component from parent and getting undefined in the console.

see the image also see the stack blaze for the same

https://stackblitz.com/edit/angular-ivy-k4m2hp?file=src%2Fapp%2Fhello.component.ts

see the image also see the stack blaze for the same

import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { TestChildComponent } from './test-child/test-child.component';

@Component({
  selector: 'hello',
  template: `<h1>this is Hello component {{name}}!</h1>`,
  styles: [`h1 { font-family: Lato; }`],
})
export class HelloComponent {
  @Input() name: string;
@ViewChild('TestChildComponent') testChildComponent: TestChildComponent
  ngOnInit() {
    console.log('calling ngOninit in hello component');
    console.log('going to call test child instance this.TestChildComponent.ngOninit')
   console.log(this.testChildComponent);
  }
}

Please help to get the child component

this.testChildComponent

So that i can call ngOnInit of child from parent.

this.testChildComponent.ngOnInit()

Douty answered 30/3, 2022 at 6:57 Comment(1)
try using ngAfterViewInit() method instead of ngOnInit()Krall
U
3

if you set your viewChild { static: true } you will be able to access it in ngOnInit

but in your sample the issue is due totestChildComponent is a child of app.component and not hello.component

<app-test-child childname="{{ name }}" #test></app-test-child>

app.component.ts

import { Component, VERSION, ViewChild } from '@angular/core';
import { TestChildComponent } from './test-child/test-child.component';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  name = 'this is from app compoenent';
  @ViewChild('test', { static: true }) testChildComponent: TestChildComponent;

  ngOnInit() {
    console.log('calling ngOninit in app component');
    console.log(this.testChildComponent);
  }
}

If you want to access testChildComponent from hello.component you will have to send it the component as an input for sample

following a working sample of accessing testChildComponent

https://stackblitz.com/edit/angular-ivy-tvwukg?file=src%2Fapp%2Fapp.component.html

Unalienable answered 30/3, 2022 at 7:10 Comment(11)
Thanks , but in my orignal project (not stackbalze ) in client location , i am getting static:trueDouty
argument of type static boolean is not assignable to parameter of type read anyDouty
Do you identify your <app-test-child childname> tag with same id pass to view child ? I don't see this error in the stackblitz aboveUnalienable
yes in stackbliz i am not getting that errorDouty
which version of angular core are you using ?Unalienable
I also found this post #56551878Unalienable
angular 8i am usingDouty
Once you upgraded to newer version of Angular. Remove node_module folder and run npm installDouty
i am trying this nowDouty
error is gone after Once you upgraded to newer version of Angular. Remove node_module folder and run npm install this change , thanksDouty
there are multiple other issue, will let you knowDouty
U
5

ViewChild element ref can be accessed in ngAfterViewInit() cycle the earliest.

enter image description here

Angular doc says we should use the child component injected by ViewChild in ngAfterViewInit. But sometimes you even can’t get it in ngAfterViewInit. The reason is, the child component is not created yet when AfterViewInit hook runs. For such a case you would have to wait more (using a setTimeout would work but it's a bad idea). Other option would be to have the child emit something to the parent, letting it know the child has been rendered and then the parent can query it.

But your case is that sibling HelloComponent wants to query sibling TestChildComponent it can't do that. TestChildComponent is just not in the scope for HelloComponent. Easiest solution would be to query TestChildComponent from the parent AppComponent.

You should also add #TestChildComponent to access the ref.

<app-test-child #TestChildComponent childname="{{ name }}"></app-test-child>

Working example: https://stackblitz.com/edit/angular-ivy-j5ceat?file=src%2Fapp%2Fapp.component.html

Unsnap answered 30/3, 2022 at 7:7 Comment(0)
U
3

if you set your viewChild { static: true } you will be able to access it in ngOnInit

but in your sample the issue is due totestChildComponent is a child of app.component and not hello.component

<app-test-child childname="{{ name }}" #test></app-test-child>

app.component.ts

import { Component, VERSION, ViewChild } from '@angular/core';
import { TestChildComponent } from './test-child/test-child.component';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  name = 'this is from app compoenent';
  @ViewChild('test', { static: true }) testChildComponent: TestChildComponent;

  ngOnInit() {
    console.log('calling ngOninit in app component');
    console.log(this.testChildComponent);
  }
}

If you want to access testChildComponent from hello.component you will have to send it the component as an input for sample

following a working sample of accessing testChildComponent

https://stackblitz.com/edit/angular-ivy-tvwukg?file=src%2Fapp%2Fapp.component.html

Unalienable answered 30/3, 2022 at 7:10 Comment(11)
Thanks , but in my orignal project (not stackbalze ) in client location , i am getting static:trueDouty
argument of type static boolean is not assignable to parameter of type read anyDouty
Do you identify your <app-test-child childname> tag with same id pass to view child ? I don't see this error in the stackblitz aboveUnalienable
yes in stackbliz i am not getting that errorDouty
which version of angular core are you using ?Unalienable
I also found this post #56551878Unalienable
angular 8i am usingDouty
Once you upgraded to newer version of Angular. Remove node_module folder and run npm installDouty
i am trying this nowDouty
error is gone after Once you upgraded to newer version of Angular. Remove node_module folder and run npm install this change , thanksDouty
there are multiple other issue, will let you knowDouty
R
1

If ViewChild is undefined in the parent component, it's possible that the child component hasn't been rendered yet.

To make sure that the child component has been rendered before using ViewChild, you can implement the ngAfterViewInit in your parent component.

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

@Component({
  selector: 'app-parent',
  template: `
    <app-child></app-child>
  `
})
export class ParentComponent implements AfterViewInit {
  @ViewChild(ChildComponent) childComponent!: ChildComponent;

  ngAfterViewInit() {
    console.log(this.childComponent);
  }
}
Rosaliarosalie answered 25/2, 2023 at 13:29 Comment(1)
This was my issue because I was toggling the visibility using ngif. I had to hook into ngInit, in order to update the component after making visible. Any other life cycle hook would cause issues with bound data.Albertinaalbertine

© 2022 - 2024 — McMap. All rights reserved.