Angular Component Output Properties

Angular Component Output Properties

In this article, I am going to discuss Angular Component Output Properties in detail.  At the end of this article, you will have a very good understanding of the below things.

  1. How to pass the user actions or user entered values or selections from the child component to the parent component using output properties.
  2. How to create custom events using angular EventEmitter class
  3. What are ng-container directive and its use
What are Angular Component Output Properties?

The Angular Component Output Properties are used to to pass the data from the nested component to the container component.

This is a continuation part of our previous article, so please read our previous article before proceeding to this article as we are going to work with the same example as shown below.

Angular Component Output Properties

At the moment when you click any of the radio buttons, then nothing is happening. Let first discuss what we want to do here.

When All(6) radio button is clicked then we need to display all the students in the table. When Male(4) radio button is clicked then we need to display only the 4 Male students in the table similarly when the Female(2) radio button is clicked then we only need to display the 2 Female students in the table.

How to achieve this?

To achieve this here we are going to make use of the Angular component Output Properties. First, let’s discuss the changes that are required in the nested component i.e. StudentCountComponent

Modify student-count.component.ts file:

Open student-count.component.ts file and then copy and paste the following code in it. The changes we have done here are self-explained so please go through the comments.

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

@Component({
  selector: 'app-student-count',
  templateUrl: './student-count.component.html',
  styleUrls: ['./student-count.component.css']
})

export class StudentCountComponent {
  @Input()
  all: number;

  @Input()
  male: number;

  @Input()
  female: number;
  // This variable holds the selected value of the radio button
  selectedRadioButtonValue: string = 'All';

  // The Output decorator makes the property of an Component as an Output property
  // The EventEmitter class in Angular is used to create the custom event
  // When the radio button selection changes, the selected radio button
  // value which is a string gets passed to the event handler method.
  // Hence, the event payload is string.
  @Output()
  countRadioButtonSelectionChanged: EventEmitter<string> =
      new EventEmitter<string>();

  // This method raises the custom event. We will bind this
  // method to the change event of all the 3 radio buttons
  onRadioButtonSelectionChange() {
      this.countRadioButtonSelectionChanged
          .emit(this.selectedRadioButtonValue);
  }
}
Modify student-count.component.html

The following are the changes that are required in the view template of StudentCountComponent i.e. student-count.component.html. Notice here we have made 3 changes on each radio button.

  1. The value attribute is set to (All, Male or Female)
  2. We implemented the 2-way data-binding using the ngModel directive. Notice the ngModel is bound to selectedRadioButtonValue property of 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.
  3. The onRadioButtonSelectionChange() method is binded to the “change” event of the radio button. That means whenever, the selection of the radio button changes, onRadioButtonSelectionChange() method raises the custom event “countRadioButtonSelectionChanged”. We defined this custom event using Angular EventEmitter class.
<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="Male"
       [(ngModel)]="selectedRadioButtonValue"
       (change)="onRadioButtonSelectionChange()">
<span class="radioClass">{{"Male(" + male + ")"}}</span>

<input name="options" type="radio" value="Female"
       [(ngModel)]="selectedRadioButtonValue"
       (change)="onRadioButtonSelectionChange()">
<span class="radioClass">{{"Female(" + female + ")"}}</span>
Modify student-list.component.ts file 

Now let’s have a look at the changes that are required in the parent component i.e. StudentListComponent. The following are the changes that are required in the StudentListComponent class. The changes are commented and self-explained.

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

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

    // This property will keep track of the radio button which is selected
    // We have set the default value to All, so all the students
    // are displayed in the table by default
    selectedStudentCountRadioButton: string = 'All';

  students: any[] = [
    {
        ID: 'std101', FirstName: 'Pranaya', LastName: 'Rout',
        DOB: '12/8/1988', Gender: 'Male', CourseFee: 1234.56
    },
    {
        ID: 'std102', FirstName: 'Anurag', LastName: 'Mohanty',
        DOB: '10/14/1989', Gender: 'Male', CourseFee: 6666.00
    },
    {
        ID: 'std103', FirstName: 'Priyanka', LastName: 'Dewangan',
        DOB: '7/24/1992', Gender: 'Female', CourseFee: 6543.15
    },
    {
        ID: 'std104', FirstName: 'Hina', LastName: 'Sharma',
        DOB: '8/19/1990', Gender: 'Female', CourseFee: 9000.50
    },
    {
        ID: 'std105', FirstName: 'Sambit', LastName: 'Satapathy',
        DOB: '4/12/1991', Gender: 'Male', CourseFee: 9876.54
    },
    {
        ID: 'std106', FirstName: 'Tarun', LastName: 'Mallick',
        DOB: '4/10/1992', Gender: 'Male', CourseFee: 1278.55
    }
];

getTotalStudentsCount(): number {
    return this.students.length;
}

getMaleStudentsCount(): number {
    return this.students.filter(std => std.Gender === 'Male').length;
}

getFemaleStudentsCount(): number {
    return this.students.filter(std => std.Gender === 'Female').length;
}

    // Depending on the radio button which is selected, this method updates
    // the selectedStudentCountRadioButton property
    // This method is going to called when the child component (StudentCountComponent)
    // raises the custom event - countRadioButtonSelectionChanged
    // The event binding is specified in StudentList.component.html
    onStudentCountRadioButtonChange(selectedRadioButtonValue: string): void {
        this.selectedStudentCountRadioButton = selectedRadioButtonValue;
    }
}
Modify student-list.component.html

The following are the changes that are required in the view template of StudentListComponent i.e. student-list.component.html. 

The onStudentCountRadioButtonChange($event) method is bound to the custom event – countRadioButtonSelectionChanged. The $event object will have the selected radio button value as that is what is passed as the event payload from the nested component. The event handler method (onStudentCountRadioButtonChange()) in the component class updates the property “selectedStudentCountRadioButton”. This property is then used along with the *ngIf structural directive to decide which student objects to display in the table.

On the <tr> element, we are using “ngIf” directive along with selectedStudentCountRadioButton property which controls the student objects to display.

Notice, just above the <tr> element, we have introduced <ng-container> element and the “ngFor” directive is placed on this element. If you are wondering why we have done this, Angular does not allow multiple structural directives to be placed on one element as shown below.  

<app-student-count [all]="getTotalStudentsCount()"
[male]="getMaleStudentsCount()"
[female]="getFemaleStudentsCount()"
(countRadioButtonSelectionChanged)="onStudentCountRadioButtonChange($event)">
</app-student-count>

<br/><br/>
<table>
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Gender</th>
            <th>DOB</th>
            <th>Course Fee</th>
        </tr>
    </thead>
    <tbody>
        <ng-container *ngFor="let student of students;">
            <tr *ngIf="selectedStudentCountRadioButton=='All' ||
                       selectedStudentCountRadioButton==student.Gender">
            <td>{{student.ID | uppercase}}</td>
            <td>{{student.FirstName | uppercase}}</td>
            <td>{{student.Gender}}</td>      
            <td>{{student.DOB | date:'dd/MM/y'}}</td>
            <td>{{student.CourseFee | currency:'USD':true:'1.2-2'}}</td>
        </tr>
    </ng-container>
        <tr *ngIf="!students || students.length==0">
            <td colspan="10">
                No Students to display
            </td>
        </tr>
    </tbody>
</table>
Modify app.module.ts:

Open app.module.ts file and then copy and paste the following code in it.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { StudentListComponent } from './student-list/student-list.component';
import { StudentCountComponent } from './student-count/student-count.component';

@NgModule({
  declarations: [
    AppComponent,
    StudentListComponent,
    StudentCountComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule 
  ],
  providers: [],
  bootstrap: [StudentListComponent]
})
export class AppModule { }

That’s it. We have done with our implementation. Now save all the changes and then run the application and you will see based on the selected radio button, the students are displayed in the table.

how to pass the data from the nested component to the container component using the Angular Component Output Properties

In the next article, I am going to discuss Angular Directives in Detail. Here, in this article, I try to explain how to pass the data from the nested component to the container component using the Angular Component Output Properties with an example. I hope this article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this article.

8 thoughts on “Angular Component Output Properties”

  1. Please upload further articles. This website is very useful for learning .net technologies and easy to understand all the topics. Looking for more angular articles

  2. Please upload further articles. This website is very useful for learning .net technologies and easy to understand all the topics. Looking for more angular articles

  3. Your all the articles are great. very clear. I would like to invited you to make wide range of tutorial like this for many other technologies.

  4. after adding ‘import { AppRoutingModule } from ‘./app-routing.module’;’ getting error ‘Can not find the module’.

  5. I am learning from this blog.I found out that here [(ngModel)]=”propertyName” is not working. It is not changing values. Instead use [ngModel]=”propertyName” (ngModel)=”propertyName=$event”

Leave a Reply

Your email address will not be published. Required fields are marked *