How to Refresh Child Component in Angular?

In one of our previous tutorials, you saw how to use Child components in Angular Material Tabs. We’ll use the same source code to see how to refresh child component.

In the app we had developed it had two tabs, one for listing employees All Employees and another for adding New Employee. Once the user had added a new employee, it didn’t refreshed the employee list in the All Employees tab. So, let’s see how you can refresh the All Employees child component.

Getting Started

Start by cloning the source code from the previous tutorial.

git clone https://github.com/jay3dec/angular-mat-tab

Navigate to the project folder, install the required dependencies and run the project.

cd angular-mat-tab
git checkout feature-tabs
npm install
npm start

You will be able to see the Angular application running.

Adding Output Emitter

On click of the save button from New Employee component, you need to add an output event emitter. Add the Output emitter in new-employee.component.ts file. Modify the saveForm method to emit from the output emitter. Here is how the modified component looks:

import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { DataService } from '../service/data.service';

@Component({
  selector: 'app-new-employee',
  templateUrl: './new-employee.component.html',
  styleUrls: ['./new-employee.component.css']
})
export class NewEmployeeComponent implements OnInit {
  
  showEmployee: Boolean = true;
  formGroup! : FormGroup;
  @Output() refreshList = new EventEmitter();
  constructor(private formBuilder : FormBuilder, private service : DataService) { }

  ngOnInit() {
    this.formGroup = this.formBuilder.group({
      fName : [''],
      lName : [''],
      age : [0],
      country : ['']
    })
  }

  saveForm(){
    this.service.addEmployee(this.formGroup.value).subscribe((response) => {
      console.log('response ', response);
      this.refreshList.emit("refresh");
    })
  }
}

Modify the app.component.html file to add the event emitter method call.

<div class="container">
  <mat-tab-group mat-align-tabs="start" >
    <mat-tab label="New Employee" >
      <app-new-employee (refreshList)="refreshList($event)"></app-new-employee>
    </mat-tab>
    <mat-tab label="All Employees" >
      <app-all-employee [refreshGrid]="refreshGrid"></app-all-employee>
    </mat-tab>
  </mat-tab-group>
</div>

Now you need to define the refreshList method in the app.component.ts file. Here is how it looks:

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'material-tabs';

  tabIndex : Tabs = Tabs.New_Employees;

  ngOnInit(){
    
  }
  
  setTab(tab : Tabs){
    this.tabIndex = tab; 
  }

  refreshList($event:any){
    console.log('refresh event ', $event);
  }
}

enum Tabs{
  New_Employees = 0,
  All_Employees = 1
}

Using ngOnChanges

Whenever the refreshList method is called we’ll update a variable called refreshGrid which will be passed to the child component app-all-employee to indicate grid refresh.

Let’s add the refreshGrid variable in app.component.ts and set it true on refreshList method call. Here is the app.component.ts file,

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'material-tabs';
  refreshGrid : boolean = false;
  tabIndex : Tabs = Tabs.New_Employees;

  ngOnInit(){
    
  }

  setTab(tab : Tabs){
    this.tabIndex = tab; 
  }

  refreshList($event:any){
    this.refreshGrid = true;
  }

}

enum Tabs{
  New_Employees = 0,
  All_Employees = 1
}

Since you are modifying the refreshGrid Input parameter to app-all-employee component, let’s add the ngOnChanges lifecycle hook to detect parameter change.

On ngOnChanges if the refreshGrid is true let’s refresh the grid. Here is how the all-employee.component.ts file looks:

import { Component, Input, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import Employee from '../model/employee';
import { DataService } from '../service/data.service';

@Component({
  selector: 'app-all-employee',
  templateUrl: './all-employee.component.html',
  styleUrls: ['./all-employee.component.css']
})
export class AllEmployeeComponent implements OnInit {

  allEmployees : Employee[] = [];
  sub! : Subscription;
  @Input() refreshGrid : boolean = false;
  constructor(private service : DataService) { }

  ngOnInit(): void {
    this.getEmployees();
  }

  getEmployees(){
    this.sub = this.service.getEmployees().subscribe((response) => {
      this.allEmployees = response;
    })
  }

  ngOnChanges(){
    if(this.refreshGrid){
      this.getEmployees();
    } 
  }

  ngOnDestroy() {
    this.sub.unsubscribe()
  }
} 

Save the above changes and start the app. Enter the details and click on the save button. Navigate to the All Employee tab and you should be able to see the newly added entry.

This won’t work the next time since you need to reset the refreshGrid parameter to false when the user navigates to the New Employee. Anyways, you got the idea about how to refresh the child component in Angular.

Source code from this tutorial is available on GitHub.