2

I'm trying to call a public method on a child component from my parent component but I'm getting the error

core.js:5967 ERROR TypeError: this.foo.bar is not a function

which I understand th is is because even though my ViewChild is of type ChildComponent it's not actually a ChildComponent, it's just the same shape as a ChildComponent but ultimately is just a plain old JS object.

So how do I call a public method on a child component?

My code looks like:

parent.html

<app-child-component #childComponent></app-child-component>

parent.ts

export class ParentComponent implements OnInit {
{
    @ViewChild('childComponent') childComponent:ChildComponent;

    ngOnInit(): void {
        this.childComponent.foo(); // ERROR TypeError: this.childComponent.foo is not a function
    }
}

childComponent.ts

export class ChildComponent implements OnInit {
{
    public foo(): void
    {
        // ...
    }
}
Greg B
  • 14,597
  • 18
  • 87
  • 141

2 Answers2

2

foo() cannot be called because the childComponent object has not been instantiated by the time the OnInit lifecycle hook fires.

From the Angular lifecycle hooks documentation:

Hook method Purpose Timing
ngOnInit() Initialize the directive or component after Angular first displays the data-bound properties and sets the directive or component's input properties. Called once, after the first ngOnChanges().

Instead you should place the call to childComponent.foo() in the AfterViewInit callback.

Hook method Purpose Timing
ngAfterViewInit() Respond after Angular initializes the component's views and child views, or the view that contains the directive. Called once after the first ngAfterContentChecked().

Your solution would then be:

export class ParentComponent implements AfterViewInit {
{
    @ViewChild('childComponent') childComponent: ChildComponent;

    ngAfterViewInit(): void {
        this.childComponent.foo(); 
    }
}
  • 1
    This isn't working for me. If I call the method in ngAfterViewInit I get `ERROR TypeError: this.childComponent.foo is not a function`. and if I `console.log(this.childComponent)` I get `ElementRef {nativeElement: app-child-component.ng-tns-c519-21}`. It's strange, I've found this StackBlitz which is exactly what I'm doing https://stackblitz.com/edit/how-to-call-child-componentss-method-from-the-parent-com-eremif?file=src/app/app.component.ts, same use of `ViewChild` same `#foo` on the element, as you can see in the StackBlitz the `console.log` shows `ChildComponent` and not `ElementRef. – Greg B Jan 15 '21 at 15:04
1

After working the problem through and getting a different error that lead me to this question I've realised that the module where the child component is defined had the component in it's declarations but not in it's exports.

What I had:

@NgModule({
    declarations: [
        ChildComponent
    ],
    imports: [
        SharedModule
    ]
})
export class ChildModule {
}

What I needed:

@NgModule({
    declarations: [
        ChildComponent
    ],
    imports: [
        SharedModule
    ],
    exports: [
        ChildComponent
    ]
})
export class ChildModule {
}
Greg B
  • 14,597
  • 18
  • 87
  • 141