Call a method of the child component

JavascriptAngular

Javascript Problem Overview


I have a nested child component like this:

<app-main>
    <child-component />
</app-main>

My appMain component needs to invoke a method on child-component.

How to invoke a method on the child-component?

Javascript Solutions


Solution 1 - Javascript

You can get a reference to an element using

@ViewChild('childComponent') child;

where childComponent is a template variable <some-elem #childComponent>` or

@ViewChild(ComponentType) child;

where ComponentType is the type of a component or directive and then in ngAfterViewInit or an event handlers call child.someFunc().

ngAfterViewInit() {
  console.log(this.child);
}

See also get hold of an element in the template

Solution 2 - Javascript

Parent and child can communicate via data binding.

Example:

@Component({
    selector: 'child-component',
    inputs: ['bar'],
    template: `"{{ bar }}" in child, counter  {{ n }}`
})
class ChildComponent{
    constructor () {
        this.n = 0;
    }
    inc () {
        this.n++;
    }
}

@Component({
    selector: 'my-app',
    template: `
        <child-component #f [bar]="bar"></child-component><br>
        <button (click)="f.inc()">call child func</button>
        <button (click)="bar = 'different'">change parent var</button>
    `,
    directives: [ChildComponent]
})
class AppComponent {
    constructor () {
        this.bar = 'parent var';
    }
}

bootstrap(AppComponent);  

Demo

#f creates a reference to the child component and can be used in template or passed to function. Data from parent can be passed by [ ] binding.

Solution 3 - Javascript

Being a son component

@Component({
    // configuration
    template: `{{data}}`,
    // more configuration
})
export class Son {

  data: number = 3;
  
  constructor() { }

  updateData(data:number) {
    this.data = data;
  }

}

Having a father component

@Component({
    // configuration
})
export class Parent {
  @ViewChild(Son) mySon: Son;

  incrementSonBy5() {
    this.mySon.updateData(this.mySon.data + 5);
  }
}

In the father's template

<son></son>
<button (click)="incrementSonBy5()">Increment son by 5</button>

This solution only works for one <son></son>instance in the parent template. If you have more than one instance only will work in the first one of the template.

Solution 4 - Javascript

The best way to access a child component is @ViewChild.

Let's say you have AppMainComponent with a nested ChildComponent from your example.

// app-main.component.ts
import { Component } from '@angular/core';

@Component({
    selector: 'app-main',
    template: `
        <child-component />
    `
})

export class AppMainComponent {}

You want to invoke a clear method from your ChildComponent.

// child.component.ts
import { Component } from '@angular/core';

@Component({
    selector: 'child-component',
    template: '{{ greeting }}'
})

class ChildComponent {
    greeting: String = 'Hello World!';

    clear() {
        this.greeting = null;
    }
}

You can accomplish it by importing the ChildComponent class, ViewChild decorator and pass component's class in it as a query. This way, you would have access to the ChildComponent's interface stored in the custom variable. Here is an example:

// app-main.component.ts
import { Component, ViewChild } from '@angular/core';
import { ChildComponent } from './components/child/child.component';

@Component({
    selector: 'app-main',
    template: `
        <child-component />
    `
})

class ChildComponent {
    @ViewChild(ChildComponent)
    child: ChildComponent;

    clearChild() {
        this.child.clear();
    }
}

Notice! Child view becomes available only after ngAfterViewInit.

> Respond after Angular initializes the component's views and child views. Called once after the first ngAfterContentChecked(). A component-only hook.

If you want to execute method automatically, you need to do it inside this lifecycle hook.

You can also get a QueryList of child components via ViewChildren decorator.

import { Component, ViewChildren, QueryList } from '@angular/core';
import { ChildComponent } from './components/child/child.component';

...

@ViewChildren(ChildComponent)
children: QueryList<ChildComponent>;

QueryList might be very useful, e.g. you can subscribe for children changes.

It's also possible to create template reference variables and get access to them via the ViewChild decorator.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPer Hornsh&#248;j-SchierbeckView Question on Stackoverflow
Solution 1 - JavascriptGünter ZöchbauerView Answer on Stackoverflow
Solution 2 - JavascriptAlexander ErmolovView Answer on Stackoverflow
Solution 3 - JavascriptpearpagesView Answer on Stackoverflow
Solution 4 - JavascriptFrelserenView Answer on Stackoverflow