Emit Events From Child To Parent Component – Angular

Angular components communicate with each other to pass data. Several angular components can form a hierarchical structure, where we can emit data and events in both directions(parent and child component).

In the previous article, we learned how to pass data from parent to child components.

In this article, we will learn how to emit events from the child to parent component with the help of the @Output and event emitter.

We will also create a small example application, where we will have two components assets and the asset-chart component, as shown below.

emit events from parent

The application will have inputs to enter the amount allocated for each asset category(Debt, Equity, and Mutual Funds).

Once the user enters the amount and clicks the Calculate button, we get the Pie chart of asset allocation on each investment category.

The chart displays the percentage of the total amount of allocation for each asset category.

emit events from parent

Emit events from component using @Output

Create an angular application with the name angular-output-emitter-example.

ng new angular-output-emitter-example

Also, add the ng-bootstrap and the chart.js libraries to the application.

cd angular-output-emitter-example
ng add @ng-bootstrap/ng-bootstrap
npm install chart.js --save

Create a new angular component with the name assets.

ng g c assets

Replace the assets.component typescript file with the below content.

This component will be the child component of the app component and emits the event on the click of a button.

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

export interface Asset {
  equity: number;
  debt: number;
  mutualFund: number;
}

@Component({
  selector: 'app-assets',
  templateUrl: './assets.component.html',
  styleUrls: ['./assets.component.css']
})
export class AssetsComponent {

  asset: Asset = { equity: 0, debt: 0, mutualFund: 0 };

  @Output('calculate-asset') calculateEvent: EventEmitter<Asset> = new  EventEmitter<Asset>();
  
  constructor() { }
  
  drawChart() {
    this.calculateEvent.emit(this.asset);
  }
}
  • We have imported the Output and the EventEmitter from the angular core library.
  • We have defined an Asset interface that holds the user inputs.
  • The drawChart() method emits the event, and also we are passing the asset value using EventEmitter.

Update the asset.component.html file with the below content.

<div class="input-group mb-3">
  <div class="input-group-prepend">
    <span class="input-group-text">Debt : $</span>
  </div>
  <input type="number" class="form-control" [(ngModel)]="asset.debt">
</div>
<div class="input-group mb-3">
  <div class="input-group-prepend">
    <span class="input-group-text">Equity : $</span>
  </div>
  <input type="number" class="form-control" [(ngModel)]="asset.equity" name="equity">
</div>
<div class="input-group mb-3">
  <div class="input-group-prepend">
    <span class="input-group-text">Mutual Funds : $</span>
  </div>
  <input type="number" class="form-control" [(ngModel)]="asset.mutualFund" name="mutualFund">
</div>
<button type="submit" (click)="drawChart()" class="btn btn-success">Calculate</button>

Users can input the invested amount and click on the Calculate button to get the asset allocation percentage.

Update the app.modules.ts file by adding the FormsModule.

//other imports
import { FormsModule } from '@angular/forms';

@NgModule({
//
  imports: [
    FormsModule,
  ],
//
})
export class AppModule { }

Creating the second child component

Create an angular component with the name asset-chart.

ng g c asset-chart

This component will be the child of the app component and will display the pie chart for the given Asset input.

Update the asset-chart.component.ts with the below content.

import { Component } from '@angular/core';
import { Asset } from '../assets/assets.component';
import { Chart } from 'chart.js';
@Component({
  selector: 'app-asset-chart',
  templateUrl: './asset-chart.component.html',
  styleUrls: ['./asset-chart.component.css']
})
export class AssetChartComponent {
  chart: any;
  constructor() { }
  asset: Asset;
  chartDataInPercentage = [];
  total = 0;
  percentage(num: number): number {
    let percentage = (num/this.total) * 100;
    return Math.round(percentage * 100) / 100;
  }
  refreshChart(asset: Asset) {
    this.asset = asset;
    this.total = this.asset.debt + this.asset.equity + this.asset.mutualFund;
    this.chartDataInPercentage = [this.percentage(this.asset.debt),
      this.percentage(this.asset.equity),
      this.percentage(this.asset.mutualFund)];
    this.chart = new Chart('canvas', {
      type: 'pie',
      data: {
        labels: ['Debt %', 'Equity %', 'Mutual Funds %'],
        datasets: [
          {
            data: this.chartDataInPercentage,
            borderColor: '#3cba9f',
            backgroundColor: [
              "Green",
              "Red",
              "Orange"
            ],
            fill: true
          }
        ]
      }
    });
  }
}
  • We have imported the Chart class from the chart.js library. The library will help us create a pie chart of our asset allocations.
  • The refreshChart() method draws the chart whenever invoked.

Update the asset-chart.component HTML file with the below content.

<div class="chart-container" style="position: relative; height:40vh; width:40vw">
  <canvas id="canvas"></canvas>
</div>

Now both of the child components are ready. We also need to wire them up by making the changes to the parent component(app component).

Update the app.component HTML file with the below content.

<div class="container my-6">
  <div class="border border-light p-3 mb-4">
    <h2 class="text-center">Asset Allocation calculator</h2>
    <div class="d-flex align-items-center justify-content-center" style="height: 350px">
      <app-assets (calculate-asset)="assetChart.refreshChart($event)"></app-assets>
      <app-asset-chart #assetChart></app-asset-chart>
    </div>
  </div>
</div>

To pass the event data from the event emitter, we also need to call refreshChart() method of the asset-chart component.

The calculate-asset is the alias used with the @Output() decorator in the assets component.

Also, the #assetChart denotes the local template variable that helps to invoke the refreshChart() method of the asset-chart component.

Testing the output

Run the Angular application. Enter the amounts and click on the Calculate button.

angular-output-example

Using @ViewChild to reference components

We can use the @ViewChild decorator to access the child component controller classes from a parent component.

Also, the @ViewChild decorator finds the correct child component controller class and initializes the instance.

Update the app.component.ts with the below code.

import { ViewChild } from '@angular/core';
import { Component } from '@angular/core';
import { AssetChartComponent} from './asset-chart/asset-chart.component'
import { Asset } from './assets/assets.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  title = 'angular-output-emitter-example';

  @ViewChild(AssetChartComponent) assetChart: AssetChartComponent;

  refresh(asset : Asset){
    this.assetChart.refreshChart(asset);
  }
}

We have imported the AssetChartComponent child component controller class and created an instance.

The instance is decorated with the @ViewChild decorator.

We have also created a refresh() method that invokes the AssetChartComponent controller class’s refreshChart() method.

Update the app.component.html with the below content.

<div class="container my-6">
  <div class="border border-light p-3 mb-4">
    <h2 class="text-center">Asset Allocation calculator</h2>
    <div class="d-flex align-items-center justify-content-center" style="height: 350px">
      <app-assets (calculate-asset)="refresh($event)"></app-assets>
      <app-asset-chart></app-asset-chart>
    </div>
  </div>
</div>

Now we can directly call the App component’s refresh() method, which also invokes the child component’s method to update the asset chart.

Run the Angular application. Enter the amounts and click the Calculate button. We get the same expected result as earlier.

angular-viewchild-example

Conclusion

In this article, we learned how to use the @Output angular decorator to emit events from a child component to the parent component.

We also learned how to pass the event data into child components with the help of the template and with the help of the @ViewChild angular decorator.

Finally, the example code is available on GitHub.

Emit Events From Child To Parent Component – Angular
Scroll to top

Discover more from ASB Notebook

Subscribe now to keep reading and get access to the full archive.

Continue reading