Question

Call a Child Component Method from a Parent in Angular

typescriptangularangular-components

Question

In an Angular application, a parent component needs to call a method on a child component. The child method logs successfully, but updating its test property does not update the displayed child template.

// Parent component
export class AppComponent {
  private notify: NotifyComponent;

  constructor() {
    this.notify = new NotifyComponent();
  }

  submit(): void {
    notify.callMethod();
  }
}

// Child component
export class NotifyComponent {
  test: string;

  callMethod(): void {
    console.log('successfully executed.');
    this.test = 'Me';
  }
}

How can the parent call the rendered child component instance so that setting test updates the child template?

Short Answer

You will learn why Angular components should not usually be created with new, how to reference a child rendered in a parent template with @ViewChild, and when that reference becomes available. You will also see how Angular updates the child view after its component state changes.

Concept

Angular creates and manages component instances from component selectors in templates. That management includes dependency injection, lifecycle hooks, change detection, and connecting the instance to its rendered DOM.

When code runs new NotifyComponent(), TypeScript creates an ordinary class object. Its callMethod() can run, so console.log() works and this.test changes on that object. However, it is not the same instance as the one Angular rendered, and Angular has not connected it to a <notify> view. Therefore, no visible template changes.

To let a parent access a child that Angular rendered, place the child selector in the parent template and query it with @ViewChild(NotifyComponent). The resulting property refers to Angular's rendered child instance.

A second issue in the original code is that instance members must be accessed through this inside class methods: this.notify, not notify.

Mental Model

Think of Angular as a theater manager.

  • Adding <notify></notify> to a template asks the manager to create an actor, put the actor on stage, and keep the stage display synchronized with the actor's state.
  • Calling new NotifyComponent() creates a separate actor backstage. That actor can speak (console.log) and change clothes (test = 'Me'), but the audience cannot see them.
  • @ViewChild gives the parent a reference to the actor Angular placed on stage.
Take Quiz

Syntax and Examples

Import ViewChild, render the child in the parent template, and declare a query for the child type.

import { Component, ViewChild } from '@angular/core';
import { NotifyComponent } from './notify.component';

@Component({
  selector: 'my-app',
  template: `
    <button (click)="submit()">Call Child Component Method</button>
    <notify></notify>
  `
})
export class AppComponent {
  @ViewChild(NotifyComponent) notify!: NotifyComponent;

  submit(): void {
    this.notify.callMethod();
  }
}

The child can remain simple:

import { Component } from '@angular/core';

@Component({
  selector: 'notify',
  template: '<h3>Notify {{ test }}</h3>'
})
export class NotifyComponent {
  test = '';

  callMethod(): void {
    console.log('successfully executed.');
    this.test = 'Me';
  }
}

@ViewChild(NotifyComponent) asks Angular for the first NotifyComponent found in this component's view. The ! is TypeScript's definite-assignment assertion: Angular assigns the property after creating the view.

Step by Step Execution

Use this parent template:

<button (click)="submit()">Call Child Component Method</button>
<notify></notify>

Execution flow:

  1. Angular creates AppComponent.
  2. Angular reads its template and sees <notify>.
  3. Angular creates a NotifyComponent instance, renders <h3>Notify {{ test }}</h3>, and assigns that instance to notify through @ViewChild.
  4. The user clicks the button, so Angular calls submit().
  5. submit() runs this.notify.callMethod() on the rendered child instance.
  6. callMethod() assigns 'Me' to the child's test property.
  7. Angular change detection updates interpolation, so the page displays Notify Me.

Do not call a view-child reference during the parent's constructor because the child view does not exist yet. If initialization must use the child reference, use ngAfterViewInit().

import { AfterViewInit, Component, ViewChild } from '@angular/core';

export class AppComponent implements AfterViewInit {
  @ViewChild(NotifyComponent) notify!: NotifyComponent;

  ngAfterViewInit(): void {
    // The child reference is available here.
    console.log(this.notify);
  }
}

Real World Use Cases

Calling a child method is useful when the parent owns an action and the child owns a focused UI behavior:

  • A parent form page tells a custom input component to focus itself.
  • A checkout page asks a payment widget to validate its current fields.
  • A dashboard tells a chart component to refresh or reset its zoom.
  • A dialog host calls open() or close() on a reusable modal component.
  • A parent wizard tells the currently displayed step to save or validate.

Use this pattern for imperative UI actions. For ordinary data flow, prefer passing values to children with @Input() and receiving events with @Output().

Take Quiz

Real Codebase Usage

In production Angular code, direct child method calls are usually kept narrow and intentional.

Guard against a missing conditional child

If the child is created with *ngIf or another conditional template block, it may not exist. Make the query optional and check it.

@ViewChild(NotifyComponent) notify?: NotifyComponent;

submit(): void {
  this.notify?.callMethod();
}

Prefer inputs for state

If the parent simply wants the child to display a value, bind the value rather than exposing a setter-like method.

// Parent template
<notify [message]="notificationMessage"></notify>
// Child
import { Component, Input } from '@angular/core';

@Component({
  selector: 'notify',
  template: '<h3>Notify {{ message }}</h3>'
})
export class NotifyComponent {
  @Input() message = '';
}
notificationMessage = '';

submit(): void {
  this.notificationMessage = 'Me';
}

This makes the data relationship visible in the template and easier to test. Reserve @ViewChild for actions such as focus(), reset(), open(), or a child API that represents behavior.

Common Mistakes

Creating a component with new

// Incorrect for a rendered Angular component
this.notify = new NotifyComponent();

This creates an unmanaged class instance. It is not the <notify> instance in the DOM. Let Angular create components through the template, then use @ViewChild to obtain its reference.

Forgetting to render the child

@Component({
  template: '<button (click)="submit()">Run</button>'
})

Without <notify></notify>, there is no child in the parent's view for @ViewChild to find.

Omitting this

submit(): void {
  notify.callMethod(); // Incorrect: no local variable named notify
}

Use the class property:

this.notify.callMethod();

Using @ViewChild in the constructor

constructor() {
  this.notify.callMethod(); // Too early
}

The view is created after construction. Call it from a click handler, or use ngAfterViewInit() for setup after the view is ready.

Selecting the wrong child

@ViewChild(NotifyComponent) returns the first matching component in the parent view. If several children exist, use a template reference variable and query it, or redesign the interaction around inputs and outputs.

Expecting a child to update from an unrelated instance

Changing test on a manually created object does not change test on Angular's rendered child. Always confirm that code is operating on the rendered instance.

Comparisons

ApproachBest forDirectionExample
@ViewChildCalling a focused child UI actionParent to childthis.notify.focus()
@Input()Giving the child data or stateParent to child<notify [message]="message">
@Output()Reporting a user action or resultChild to parent(dismissed)="onDismiss()"
Shared serviceState or actions across unrelated componentsMany directionsNotification store service
new SomeComponent()Almost never for Angular UI componentsNot connected to AngularCreates only a plain object

@ViewChild is imperative: the parent tells the child to perform an action. @Input() is declarative: the parent describes the child state through bindings. Prefer declarative bindings when the goal is simply to display or synchronize data.

Take Quiz

Cheat Sheet

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

@Component({
  template: `
    <button (click)="run()">Run</button>
    <app-child></app-child>
  `
})
export class ParentComponent {
  @ViewChild(ChildComponent) child!: ChildComponent;

  run(): void {
    this.child.someMethod();
  }
}
  • Put the child selector in the parent template.
  • Import ViewChild from @angular/core.
  • Query the child using its component class: @ViewChild(ChildComponent).
  • Access class fields with this.child.
  • The query is available after the view is created; use ngAfterViewInit() for setup code.
  • If the child may not render, use child?: ChildComponent and this.child?.someMethod().
  • Do not use new ChildComponent() to interact with a rendered Angular child.
  • Prefer @Input() for data and @Output() for child-to-parent events.

FAQ

Why does new ChildComponent() not update the Angular page?

It creates a separate plain TypeScript object. Angular did not render that object or connect it to change detection and a template.

Why is @ViewChild undefined in the constructor?

Angular has not created the component view and its children during construction. The reference is available after view creation, such as in ngAfterViewInit().

Should I use @ViewChild to pass text to a child component?

Usually no. Use an @Input() binding for text, configuration, and other state. Use @ViewChild for behavior-oriented methods like focus() or reset().

Can a parent access more than one child component?

Yes. Use @ViewChildren(ChildComponent) to receive a QueryList of matching child instances.

What if the child is inside *ngIf?

The child reference exists only while the conditional template renders it. Use an optional query and check for it before calling a method.

Does Angular update the template after a child method changes a property?

Yes, for normal Angular event handling such as a button click, Angular runs change detection and updates interpolation like {{ test }}.

Can I query a child by a template reference variable?

Yes. Add a reference such as <notify #notification></notify> and use @ViewChild('notification') when that makes the selected element or component clearer.

Take Quiz

Mini Project

Description

Build a small notification panel. The parent page has buttons that tell a rendered child component to show a message and clear it. This demonstrates using @ViewChild for child behavior while keeping the child responsible for its own display.

Goal

Call show() and clear() on a child notification component from a parent component.

Requirements

Render the notification component inside the parent template. Use @ViewChild to obtain the rendered child instance. Add a button that displays a success message. Add a button that clears the message. Show the current message in the child template.

Take Quiz

Keep learning

Related questions

View more