Petey
Petey

Reputation: 3357

How to call a method in a child component from a parent component?

Okay the title may be a little confusing. My child component is in its own module and is using services that aren't available to the parent component.

I want to change some values in the child component on click of a button and was messing around and set something up like this.

@Component({
 selector: 'app-parent-component'
 template: `
 <button (click)="refreshData()" />
 <app-child-component> </app-child-component>
`
})
export class ParentComponent{
 refreshData() {
   ChildComponent.runRefresh()
 }
}

@Component({
 selector: 'app-child-component'
 template: ``
})
export class ChildComponent{
 static runRefresh() {
   console.log('refreshing')
   // Do things involving data on a service scoped to this component/module
 }
}

I was curious if there was something inherently wrong with this approach? Are there better ways to solve the problem. Im familiar with checking for the changes in NgOnChanges event.

I guess what i'm trying to do is call a method inside of the child component, that uses the child component resources on a scoped service, from a parent component.

Edit: Also aware of using @ViewChild and not making the child components method static. Maybe that is the only "right" way?

Upvotes: 1

Views: 1113

Answers (2)

Martin Parenteau
Martin Parenteau

Reputation: 73761

If runRefresh is a public method of the child component:

export class ChildComponent{
  public runRefresh() {
    ...
  }
}

you can call it directly in the parent template by referring to the child component with the help of a template reference variable:

<button (click)="child.runRefresh()" />
<app-child-component #child></app-child-component>

See this stackblitz for a demo.

Upvotes: 4

enno.void
enno.void

Reputation: 6579

The easiest way is to write a service that provide an event, emit in parent, subscribe in the childs.

Another way:

You can write a directive that provides a component reference:

import { Directive, TemplateRef } from '@angular/core';

@Directive({
  selector: '[selectordirective]',
})
export class SelectorDirective  {
  constructor(public cmpRef: ChildComponent) { }
}

Attach it to your childs:

<app-child-component selectordirective> </app-child-component>

Use ViewChild to read the reference in ParentComponent:

@ViewChild(SelectorDirective) child !: SelectorDirective;

  ngAfterViewInit() {
    child.cmpRef.runRefresh()
  }

Upvotes: 0

Related Questions