Learn Angular ngFor built-in directive and trackBy

Introduction
*ngFor is a structural and built-in directive that is used to iterate over collections like an array and create a template for each item.
What is Structural Directive?
A structural directive adds and removes elements in the DOM tree. Here, *ngFor does the same.
Basic Syntax of ngFor
  1. <tr *ngFor="let s of students">  
  2.    <td>{{s.Name}}</td>  
  3. </tr>  
Example
Let’s take an example and understand this with the help of it - Suppose we have list of student objects with some of their information, like StudentID, Name, DOB, StuClass, Gender, Age & Address.
  1. [  
  2.    { studentID: 1, studentName: 'Steve', gender: 'Male', age: 35, course: 'MCA' },  
  3.    { studentID: 2, studentName: 'Bobby', gender: 'Male', age: 32, course: 'MBA' },  
  4.    { studentID: 3, studentName: 'Rina', gender: 'Female', age: 45, course: 'B.Tech' },  
  5.    { studentID: 4, studentName: 'Alex', gender: 'Female', age: 24, course: 'M.Tech' },  
  6. ]  
And, we want to have this data in HTML table format, like below.





This is how we can do using ngFor directive introduced in Angular.
Let’s look at it via code.
Step 1
Let’s create a folder named Student under src/app folder.
Add a TypeScript file named student.component.ts under this folder and add the below code into it.
  1. import {Component} from '@angular/core'  
  2.   
  3. @Component({  
  4.     selector: 'list-student',  
  5.     templateUrl: 'app/student/student.component.html',  
  6.     styles: [  
  7.                 `  
  8.                     td {  
  9.                             border: 1px solid black;  
  10.                             padding:4px;  
  11.                     }  
  12.                     th {  
  13.                         border: 1px solid black;  
  14.                         padding:4px;  
  15.                     }  
  16.                 `  
  17.             ]  
  18. })  
  19. export class StudentListComponent {  
  20.     students: any[] =   
  21.  [  
  22.    { studentID: 1, studentName: 'Steve', gender: 'Male', age: 35, course: 'MCA' },  
  23.    { studentID: 2, studentName: 'Bobby', gender: 'Male', age: 32, course: 'MBA' },  
  24.    { studentID: 3, studentName: 'Rina', gender: 'Female', age: 45, course: 'B.Tech' },  
  25.    { studentID: 4, studentName: 'Alex', gender: 'Female', age: 24, course: 'M.Tech' },  
  26.  ];  
  27. }  
For making the class named StudentistComponent an Angular component, I decorated it with component decorator by importing component from Angular core.
templateUrl 

For using view of this component, I used templateUrl property to assign an external HTML file.
Styles 

For applying CSS styling over table output, I included some style code under styles property. We can use also styleUrls property in case we want to use some external CSS file for styling.
Step 2
Let’s add a view file named student.component.html under student folder,
And add the below HTML code into this this file,
  1. <table>  
  2.     <thead>  
  3.         <tr>  
  4.             <th>Student ID</th>  
  5.             <th>Name</th>  
  6.             <th>Gender</th>  
  7.             <th>Age</th>  
  8.             <th>Course</th>  
  9.         </tr>  
  10.     </thead>  
  11.     <tbody>  
  12.         <tr *ngFor="let s of students">  
  13.             <td>{{s.studentID}}</td>  
  14.             <td>{{s.studentName}}</td>  
  15.             <td>{{s.gender}}</td>  
  16.             <td>{{s.age}}</td>  
  17.             <td>{{s.course}}</td>  
  18.         </tr>  
  19.     </tbody>  
  20. </table>  
*ngFor
It’s a built-in directive that is used to iterate over student list and add student item in the DOM tree.
Step 3
Under app folder, open app.component.ts file and add the list-student directive as view, 
  1. import { Component } from '@angular/core';  
  2.   
  3. @Component({  
  4.   selector: 'my-app',  
  5.   template: `<list-student></list-student>`,  
  6. })  
  7. export class AppComponent {  
  8.     name = 'Angular2 Student Demo';  
  9. }   
Step 4
Under the same app folder, open app.module.ts file and import the student component as well as add your component under declarations like below,
  1. import { NgModule }      from '@angular/core';  
  2. import { BrowserModule } from '@angular/platform-browser';  
  3.   
  4. import { AppComponent } from './app.component';  
  5. import { StudentListComponent } from './student/student.component'  
  6.   
  7. @NgModule({  
  8.     imports: [BrowserModule],  
  9.     declarations: [AppComponent, StudentListComponent],  
  10.   bootstrap:    [ AppComponent ]  
  11. })  
  12. export class AppModule { }  
Step 5
Now, our application is ready to show the expected output. Let’s run our project using F5 and see the output in browser.












There are couple of local variables with ngFor built-in structural directive provided by Angular, which is used for getting the index of current element while iteration and for getting last or first element from the collection etc. as mentioned below –
  1. Index – Used for provide the index for current element while iteration.
  2. First – Return true if current element is first element in the iteration otherwise false.
  3. Last – Return true if current element is last element in the iteration otherwise false.
  4. Even – Return true if current element is even element based on index in the iteration otherwise false.
  5. Odd – Return true if current element is odd element based on index in the iteration otherwise false.
Let’s understand all these local variables with the help of an example –
Here, I am using the same student application which I used in my previous article for *ngFor directive. Look at my previous article on *ngFor directive.
Index with *ngFor directive
    The index gives the index of the current element in the iteration. Let’s look into the example below. I have a list of students which I am displaying in the table on the web page as below. Now, I want to add one more column of index at first position, which will represent of index value of each item like below,














    Let’s add the code for displaying the index of the current item in student.component.html file and run it for the expected output – (highlighted code)
    1. <table>  
    2.     <thead>  
    3.         <tr>  
    4.             <th>Index</th>  
    5.             <th>Student ID</th>  
    6.             <th>Name</th>  
    7.             <th>Gender</th>  
    8.             <th>Age</th>  
    9.             <th>Course</th>  
    10.         </tr>  
    11.     </thead>  
    12.     <tbody>  
    13.         <tr *ngFor="let s of students;let i=index">  
    14.             <td>{{i}}</td>  
    15.             <td>{{s.studentID}}</td>  
    16.             <td>{{s.studentName}}</td>  
    17.             <td>{{s.gender}}</td>  
    18.             <td>{{s.age}}</td>  
    19.             <td>{{s.course}}</td>  
    20.         </tr>  
    21.     </tbody>  
    22. </table>  
    Output










    First & Last with *ngFor directive
      First & Last both provides the Boolean value. Returns true if current element value is first element or last element otherwise false. Let’s look into highlighted code & example below,
      1. <th>Course</th>  
      2. <th>First Element</th>  
      3. <th>Last Element</th>  
      4. </tr>  
      5. </thead>  
      6. <tbody>  
      7.     <tr *ngFor="let s of students;let i=index;let f=first;let l=last">  
      8.         <td>{{i}}</td>  
      9.         <td>{{s.studentID}}</td>  
      10.         <td>{{s.studentName}}</td>  
      11.         <td>{{s.gender}}</td>  
      12.         <td>{{s.age}}</td>  
      13.         <td>{{s.course}}</td>  
      14.         <td>{{f}}</td>  
      15.         <td>{{l}}</td>  
      16.     </tr>  
      17. </tbody>  
      18. </table>  
      Output









      Even & Odd with *ngFor directive
        Even & odd both provides the Boolean value. Returns true if current element value is even element based on index or odd element based on index, otherwise false. Let’s look into highlighted code & example below,
        1. <th>Last Element</th>  
        2. <th>Even Element</th>  
        3. <th>Odd Element</th>  
        4. </tr>  
        5. </thead>  
        6. <tbody>  
        7.     <tr *ngFor="let s of students;let i=index;let f=first;let l=last;let ev=even;let od=odd">  
        8.         <td>{{i}}</td>  
        9.         <td>{{s.studentID}}</td>  
        10.         <td>{{s.studentName}}</td>  
        11.         <td>{{s.gender}}</td>  
        12.         <td>{{s.age}}</td>  
        13.         <td>{{s.course}}</td>  
        14.         <td>{{f}}</td>  
        15.         <td>{{l}}</td>  
        16.         <td>{{ev}}</td>  
        17.         <td>{{od}}</td>  
        18.     </tr>  
        19. </tbody>  
        20. </table>  
        Output








        trackBy with *ngFor directive
        To iterate over a collection in Angular 2, I used *ngFor directive in above example.
        Let’s understand with the same example why we needed trackBy function with *ngFor directive,
        Suppose we have some data coming from some API request into the collection and we need to change the data over the web page using ngFor directive. In this case, Angular will remove all the DOM elements that associated with the data and will create them again in the DOM tree, even the same data is coming (as shown in below screenshot). That means a lot of Dom manipulations will happen if a large amount of data coming from the API.



























        The solution is, we can use trackBy function, which will be helpful for Angular to track the items which have been added or removed.
        TrackBy function will take two arguments first is index and second is current item and we can return the unique identifier as a return argument.
        Let’s add the below function into student.component.ts file and look now,
        1. trackByStudentID(index: number, student: any): string {  
        2.     return student.studentID;  
        3. }  
        Updated student.component.ts code file,
        1. export class StudentListComponent {  
        2.     students: any[];  
        3.     constructor() {  
        4.         this.students = [{  
        5.             studentID: 1,  
        6.             studentName: 'Steve',  
        7.             gender: 'Male',  
        8.             age: 35,  
        9.             course: 'MCA'  
        10.         }, {  
        11.             studentID: 2,  
        12.             studentName: 'Bobby',  
        13.             gender: 'Male',  
        14.             age: 32,  
        15.             course: 'MBA'  
        16.         }, {  
        17.             studentID: 3,  
        18.             studentName: 'Rina',  
        19.             gender: 'Female',  
        20.             age: 45,  
        21.             course: 'B.Tech'  
        22.         }, {  
        23.             studentID: 4,  
        24.             studentName: 'Alex',  
        25.             gender: 'Female',  
        26.             age: 24,  
        27.             course: 'M.Tech'  
        28.         }, ];  
        29.     }  
        30.     getStudents(): void {  
        31.         this.students = [{  
        32.             studentID: 1,  
        33.             studentName: 'Steve',  
        34.             gender: 'Male',  
        35.             age: 35,  
        36.             course: 'MCA'  
        37.         }, {  
        38.             studentID: 2,  
        39.             studentName: 'Bobby',  
        40.             gender: 'Male',  
        41.             age: 32,  
        42.             course: 'MBA'  
        43.         }, {  
        44.             studentID: 3,  
        45.             studentName: 'Rina',  
        46.             gender: 'Female',  
        47.             age: 45,  
        48.             course: 'B.Tech'  
        49.         }, {  
        50.             studentID: 4,  
        51.             studentName: 'Alex',  
        52.             gender: 'Female',  
        53.             age: 24,  
        54.             course: 'M.Tech'  
        55.         }, {  
        56.             studentID: 5,  
        57.             studentName: 'Rahul',  
        58.             gender: 'Male',  
        59.             age: 26,  
        60.             course: 'MCA'  
        61.         }, ];  
        62.     }  
        63.     trackByStudentID(index: number, employee: any): string {  
        64.         return employee.studentID;  
        65.     }  
        66. }  
        Let’s add trackBy function in student.component.html view file,
        1. <th>Odd Element</th>  
        2. </tr>  
        3. </thead>  
        4. <tbody>  
        5.     <tr *ngFor="let s of students;let i=index;let f=first;let l=last;let ev=even;let od=odd;trackBy:trackByStudentID">  
        6.         <td>{{i}}</td>  
        7.         <td>{{s.studentID}}</td>  
        8.         <td>{{s.studentName}}</td>  
        9.         <td>{{s.gender}}</td>  
        10.         <td>{{s.age}}</td>  
        11.         <td>{{s.course}}</td>  
        12.         <td>{{f}}</td>  
        13.         <td>{{l}}</td>  
        14.         <td>{{ev}}</td>  
        15.         <td>{{od}}</td>  
        16.     </tr>  
        17. </tbody>  
        18. </table> <br /> <button (click)='getStudents()'>Get More Students</button>  
        Let’s look now at output and DOM elements in developer tools,













        In the above example, on clicking "Get More Students" button, all the DOM elements are not affected, but only last one element has changed color of <tr> tag. That means Angular is now able to track all the items in the collection with the help of trackBy function.
        Summary
        This article described how to use ngFor built-in structural directive and its local variables and trackBy function with ngFor directive; why we need trackBy function; and how Angular tracks all the elements with the help of trackBy function.
        To setup Angular project in your Visual Studio, download the "Quick Start Project" from the given link and use the contents from the downloaded folder into your project.

        Write me in the comment box in case you want some help in setting up Angular into your Visual Studio.

        2 comments:

        1. Learn Angular 5 from scratch with my Angular 5 Video Tutorial. YouTube link here - https://www.youtube.com/watch?v=QQTQb-OAMVQ
          https://www.youtube.com/watch?v=To_vaO4Rd6Q

          ReplyDelete
        2. Subscribe channel for upcoming Angular 5 tutorial videos. Keep watching, Keep Studying!

          ReplyDelete