Angular @Output() Directive

In my previous article, I have already discussed @Input directive; i.e., how to send data from parent component to child component:

In this article, we are going to talk about how to send data from child component to parent component using the @Output() directive. For simplicity, I am going to use the same code which I have used in my previous article and I will add some more code to explain output directive so in case you missed reading my previous article, then I would recommend you read that first, using the above link.

Angular Output Directive

See the above screen; in this example, my requirement is to notify and send the selected radio button value, i.e., [Male, Female, All] from child component to parent component so that once the user selects the radio button, the respective data gets displayed in the parent, i.e., student list component.

For exxample – if a user selects Male, then student list component will display only male student and so on. For this, we’ll start from the child component, i.e., student-count component.

Step 1

Let’s open student-count.component.ts file and paste the below code.

  1. import { Component, Input, Output, EventEmitter } from "@angular/core";  
  2. @Component({  
  3.     selector: 'student-count',  
  4.     templateUrl: './app/student-count.component.html'  
  5. })  
  6. export class StudentCountComponent {  
  7.     @Input()  
  8.     totalStudentsCount: any;  
  9.     @Input()  
  10.     maleStudentsCount: any;  
  11.     @Input()  
  12.     femaleStudentsCount: any;  
  13.     //this variable is use to select the All Radio button by default  
  14.     selectedRadioButton: any = "All";  
  15.   
  16.     //Now once user click on the radio button we need to raise custom event and notify the parent component  
  17.     //and along with the event we need to send the selected radio button value   
  18.     //That's why I have created the below property and used @Output() directive to turn that into event   
  19.     //and I am using one more class i.e EventEmitterClass to create the custom event  
  20.     //And while creating the object of the EventEmitter I am Passing string as a Payload so that we will send selected radio button value to the parent component   
  21.     @Output()  
  22.     radioButtonSelectionChanged: EventEmitter<string> = new EventEmitter<string>();  
  23.     //This function will get called when someone clicks on the radio button  
  24.     //And to this function I am passing the selected radio Button value and inside this function will raise our custom event radioButtonSelectionChanged  
  25.     //using the emit method of EventEmitter class  
  26.     selectedRadioButtonChanged(selectedRadioButtonValue) {  
  27.         this.radioButtonSelectionChanged.emit(selectedRadioButtonValue);  
  28.     }  
  29. }  

In the above code, I have just created the custom event using the @Output directive and the Event Emitter class which is present in the @angular/Core package.

And then, I have added one simple function, i.e., selectedRadioButtonChange() which gets called when user clicks on the any, i.e., All, Male, Female, radio button. In that function, we are raising the custom event using the emit method of the EventEmitter class and we are passing the selected radio button value as payload to custom event.

Step 2

Open student-count.component.html to add some HTML code.

  1. <div class="container">  
  2.     <p style="font-weight: bold;">Select:</p>  
  3.     <form>  
  4.         <label class="radio-inline">  
  5.             <!-- In below tag I have just added this event (change)="selectedRadioButtonChanged('All')"  and the I am passing selected radio button value  
  6.             To the event handler function. Same way I have done for remaining radio buttons  
  7.             -->  
  8.             <input type="radio" name="optradio" value="All" [(ngModel)]="selectedRadioButton" (change)="selectedRadioButtonChanged('All')">All({{totalStudentsCount}})  
  9.         </label>  
  10.         <label class="radio-inline">  
  11.             <input type="radio" name="optradio" value="Male" [(ngModel)]="selectedRadioButton" (change)="selectedRadioButtonChanged('Male')">Male({{maleStudentsCount}})  
  12.         </label>  
  13.         <label class="radio-inline">  
  14. <input type="radio" name="optradio" value="Female" [(ngModel)]="selectedRadioButton" (change)="selectedRadioButtonChanged('Female')">Female({{femaleStudentsCount}})  
  15.         </label>  
  16.     </form>  
  17. </div>  

In the above HTML code, I have added a change event on each and every radio button which will eventually raise our custom event (see the comments in HTML code for more information).

Step 3

Open the student-list.component.html file and paste the following code.

  1. <h4 style="text-align: center">@Output() Directive(To send data from child to parent)</h4>  
  2. <hr>  
  3. <html lang="en">  
  4. <head>  
  5.     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">  
  6. </head>  
  7. <body>  
  8.     <!--Here we are using selector as directive to call(render) the child component(student-count.component.ts) -->  
  9.     <!--Now using the property binding in selector tag we are passing data to input properties  
  10.         present in child component(student-count.component.ts)  
  11.         ex.[totalStudentsCount]="getTotalStudentsCount()"  
  12.     -->   
  13.     <!--and same we are binding our custom event -->  
  14.     <student-count [totalStudentsCount]="getTotalStudentsCount()"   
  15.                    [maleStudentsCount]="getMaleStudentsCount()"  
  16.                    [femaleStudentsCount]="getFemaleStudentsCount()"  
  17.                    (radioButtonSelectionChanged)="radioButtonChangedEventHandler($event)">  
  18.     </student-count>  
  19.     <hr>  
  20.     <div class="container">  
  21.         <table class="table table-sm">  
  22.             <thead>  
  23.                 <tr>  
  24.                     <th scope="col">Id</th>  
  25.                     <th scope="col">Name</th>  
  26.                     <th scope="col">Address</th>  
  27.                     <th scope="col">Gender</th>  
  28.                 </tr>  
  29.             </thead>  
  30.             <tbody>  
  31.                 <!--using *ngFor directive to iterate over student list-->  
  32.                 <ng-container *ngFor="let student of students">  
  33.                 <tr *ngIf="selectedRadioButtonValue=='All' || selectedRadioButtonValue == student.Gender">  
  34.                     <th scope="row">{{student.Id}}</th>  
  35.                     <td>{{student.Name}}</td>  
  36.                     <td>{{student.Address}}</td>  
  37.                     <td>{{student.Gender}}</td>  
  38.                 </tr>  
  39.             </ng-container>  
  40.             </tbody>  
  41.         </table>  
  42.     </div>  
  43. </body>  
  44.   
  45. </html>  

In the above code of student list component, I have used my previous article's code as it is and apart from that, I have added the below line on my child components selector directive to raise and handle the custom event.

  1. (radioButtonSelectionChanged)="radioButtonChangedEventHandler($event)"  

So, we are raising radioButtonSlection changed custom event using the @Output and EventEmitter class and radioButtonChangedEventHandler($event)" is our event handler function which will get called whenever the user clicks on any of the radio buttons.

  1. <tr *ngIf="selectedRadioButtonValue=='All' || selectedRadioButtonValue == student.Gender">  

 And in my code, I am using one more directive; i.e. ng-container directive, as we cannot add two structure directives on the same element - *ngIf and *ngFor

  1. <ng-container *ngFor="let student of students">  

 See the comments in the above code for more information.

Step 4

Open the student-list.component.ts file and paste the following code.

  1. import { Component } from '@angular/core'  
  2. import { FormGroup, FormControl } from '@angular/forms'  
  3. @Component({  
  4.     selector: 'my-app',  
  5.     templateUrl: './app/student-list.component.html',  
  6. })  
  7. // This is parent(container) component which contains child(nested) Component(student-count.component.ts)   
  8. export class StudentListComponent {  
  9.     selectedRadioButtonValue: any = 'All';  
  10.     public students: any;// this variable holds the list of students  
  11.     constructor() {  
  12.         this.students = [  
  13.             { Id: 1, Name: "Mahesh", Address: "Thane", Gender: "Male" },  
  14.             { Id: 2, Name: "Nishikant", Address: "Chembur", Gender: "Male" },  
  15.             { Id: 3, Name: "Sameer", Address: "Mulund", Gender: "Male" },  
  16.             { Id: 4, Name: "Nitin", Address: "Nahur", Gender: "Male" },  
  17.             { Id: 4, Name: "Siri", Address: "Worli", Gender: "Female" }  
  18.         ];  
  19.     }  
  20.     //Below for simplicity i have created 3 method to get the count of students based on the gender  
  21.     //We can do that in single method by passing the parameter.  
  22.     getTotalStudentsCount() {  
  23.         return this.students.length;  
  24.     }  
  25.     //Get the maleStudentsCount  
  26.     getMaleStudentsCount() {  
  27.         return this.students.filter(student => student.Gender == 'Male').length;  
  28.     }  
  29.     //Get the femaleStudentsCount  
  30.     getFemaleStudentsCount() {  
  31.         return this.students.filter(student => student.Gender == 'Female').length;  
  32.     }  
  33.     radioButtonChangedEventHandler(radioButtonValue) {  
  34.         this.selectedRadioButtonValue = radioButtonValue;  
  35.     }  
  36. }  

In the above code, I have used the same code from the input directive example and apart from that, I have added one event handler function which will handle our custom event. In this function, I’m just assigning the value to one variable which we are using to filter the data in our HTML template.

Html output screenshot
Html output screenshot

In the above image, we are getting the respective students once the user clicks on the radio button using @Output() directive. In this way, we can pass data from Child component to Parent component and create and raise the custom event using the @Output directive and Event Emitter class.

I hope this will help you.

Thanks.

You can download the complete code from my GitHub repository using below link.

https://github.com/mahesh353/OutputDirective