Angular Component Output Properties

In this blog article, we will discuss about sending user events from Child Component to Parent Component using @Output() decorator, @EventEmitter and ng-container directive.

Read my previous blog article Angular Component Input Properties before proceeding this article.

Continuing the previous artilce, at the moment when we click the radio buttons, nothing happens. Let us load the table based on the radio button filtering by courses.

Step 1: Update the child.component.ts class like below.

  • Here we have imported Output and EventEmitter from @angular/core.
  • Now add string property as selectedRadioButtonValue: string = 'All'
  • Add @Output() childEvent = new EventEmitter()
  • Add @Output() countRadioButtonSelectionChanged: EventEmitter = new EventEmitter()
  • Add event method onRadioButtonSelectionChange()

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

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

  @Input() all: number;
  @Input() python: number;
  @Input() angular: number;

  selectedRadioButtonValue: string = 'All';

  @Output() childEvent = new EventEmitter();

  @Output() countRadioButtonSelectionChanged: EventEmitter<string> =
                                        new EventEmitter<string>();

  constructor() { }

   onRadioButtonSelectionChange() {
    this.countRadioButtonSelectionChanged
        .emit(this.selectedRadioButtonValue); 
}

  ngOnInit() {
  }

}

Now update the child.component.html as below

  • Here we have added [(ngModel)] to all the input radio buttons. Implemented 2 way data-binding using the ngModel directive. ngModel is bound to selectedRadioButtonValue property in the component class. This 2 way data-binding ensures whenever the radio button selection changes, the selectedRadioButtonValue property is updated with the value of the selected radio button. Inside app.module.ts file Import Forms module from ‘@angular/forms’ and add in imports. [(ngModel)] only works after importing Forms Module.
  • Added change event onRadioButtonSelectionChange() for all input radio buttons. onRadioButtonSelectionChange() method is binded to “change” event of the radio button. Whenever, the selection of the radio button changes, onRadioButtonSelectionChange() method raises the custom event countRadioButtonSelectionChanged and we have created this using EventEmitter.
<span class="radioClass">Show : </span>

<input name='options' type='radio' value="All"
[(ngModel)]="selectedRadioButtonValue"
(change)="onRadioButtonSelectionChange()"
>

<span class="radioClass">{{'All(' + all + ')'}}</span>

<input name="options" type="radio" value="Python"
[(ngModel)]="selectedRadioButtonValue"
(change)="onRadioButtonSelectionChange()"
>
<span class="radioClass">{{"Python(" + python + ")"}}</span>

<input name="options" type="radio" value="Angular"
[(ngModel)]="selectedRadioButtonValue"
(change)="onRadioButtonSelectionChange()"
>

<span class="radioClass">{{"Angular(" + angular + ")"}}</span>

Step 2: Now update the parent.component.ts file as below

  • Here we have added selectedCourseCountRadioButton string
  • Added onCourseCountRadioButtonChange() method
  • onCourseCountRadioButtonChange($event) method is bound to the custom event – countRadioButtonSelectionChanged. The $event object will have the selected radio button value as that is passed as the event payload from the nested component. The event handler method (onCourseCountRadioButtonChange()) in the component class updates the property “selectedCourseCountRadioButton”. This property is then used with *ngIf structural directive to decide which Course objects to display in the table.
import { Component, OnInit } from '@angular/core';

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

  selectedCourseCountRadioButton: string = 'All';

  constructor() {

    this.courses = [
      {
          coursecode: 'PY', coursename: 'Python', fee: 5500, student: 'Girish'
      },
      {
        coursecode: 'NG', coursename: 'Angular', fee: 3000, student: 'Santosh'

      },
      {
        coursecode: 'NG', coursename: 'Angular', fee: 3000, student: 'Sanjay'

      },
      {
        coursecode: 'PY', coursename: 'Python', fee: 3000, student: 'Ramesh'

      },
      {
        coursecode: 'PY', coursename: 'Python', fee: 5500, student: 'Ganesh'

      },
      {
        coursecode: 'PY', coursename: 'Python', fee: 5500, student: 'Govind'

      },  {
        coursecode: 'PY', coursename: 'Python', fee: 5500, student: 'Gopal'

      },
      {
        coursecode: 'PY', coursename: 'Angular', fee: 5500, student: 'Saravana'

      },
  ];
   }

getTotalCourseCount(): number {
    return this.courses.length;
}

getPythonCourseCount(): number {
    return this.courses.filter(e => e.coursename === 'Python').length;
}

getAngularCourseCount(): number {
    return this.courses.filter(e => e.coursename === 'Angular').length;
}

onCourseCountRadioButtonChange(selectedRadioButtonValue: string): void {
  this.selectedCourseCountRadioButton = selectedRadioButtonValue;
}
 
  ngOnInit() {
  }

}

Now update the parent.component.html as below

  • Here we have added countRadioButtonSelectionChanged event to child component
  • Added ng-container to the table row to use the structural directives (*ngFor and *ngIf)
<app-child [all]="getTotalCourseCount()"
                [python]="getPythonCourseCount()"
                [angular]="getAngularCourseCount()"
                (countRadioButtonSelectionChanged)="onCourseCountRadioButtonChange($event)"
                >
</app-child>
<br /><br />
<table>
    <thead>
        <tr>
            <th>Code</th>
            <th>Name</th>
            <th>Fee</th>
            <th>Student</th>
         </tr>
    </thead>
    <tbody>
         <ng-container *ngFor="let course of courses;">
            <tr *ngIf="selectedCourseCountRadioButton=='All' ||
                       selectedCourseCountRadioButton==course.coursename">
                       <td>{{course.coursecode }}</td>
                       <td>{{course.coursename }}</td>
                       <td>{{course.fee}}</td>
                       <td>{{course.student}}</td>
            </tr>
        </ng-container>
        <tr *ngIf="!courses || courses.length==0">
            <td colspan="5">
                No courses to display
            </td>
        </tr>
    </tbody>
</table>

Now you can see the updates in the table whenever we select the relavant radio buttons.

References

  • https://angular.io/guide/template-syntax#input-and-output-properties

Learn more about Angular features in the next upcoming blog articles.

Happy Learning!