In the tutorial, we introduce how to use Angular ngFor
, a built-in directive, to iterate over a collection.
Related posts:
– Angular 6 Component – How to create & integrate New Angular 6 Component
– Angular 6 Service – with Observable Data for Asynchronous Operation
– Angular NgIf Else Then – NgIf with Observables and Async Pipe (Angular 6)
Contents
Technologies
- Node.js – version v10.4.0
- Angular – version 6
- Visual Studio Code – version 1.24.0
NgFor Repeater Directive
Preparation
We create an Angular 6 project as below structure:
Create Angular Project
Generate Angular Project:
Generate Customer classes:
Implement Mock Data
Create data class in src/app/customer.ts
file:
export class Customer { id: number; firstname: string; lastname: string; age: number } |
Mock Customer data in src/app/mock-customers.ts
file:
import { Customer } from './Customer'; export const CUSTOMERS: Customer[] = [ {id: 1, firstname: 'Mary', lastname: 'Taylor', age: 24}, {id: 2, firstname: 'Peter', lastname: 'Smith', age: 18}, {id: 3, firstname: 'Lauren', lastname: 'Taylor', age: 31} ]; |
*ngFor
Iterate over Array Data
Modify app.component.ts
file to provide array data:
import { Component, OnInit } from '@angular/core'; import { Customer } from './customer'; import { CUSTOMERS } from './mock-customers'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit{ customers: Customer[]; constructor() { } ngOnInit() { this.customers = CUSTOMERS; } } |
-> Modify template app.component.html
file, using *ngFor
:
<h1>Customer List</h1> <ul> <li *ngFor="let customer of customers"> {{ customer | json }} </li> </ul> |
-> result:
Iterate over Observable Data
– Modify app.component.ts
file to provide Observable data:
import { Component, OnInit } from '@angular/core'; import { Observable, of } from 'rxjs'; import { Customer } from './customer'; import { CUSTOMERS } from './mock-customers'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit{ observableCustomers: Observable<Customer[]>; constructor() { } ngOnInit() { this.observableCustomers = of(CUSTOMERS); } } |
-> Modify template file app.component.html
with async
pipe:
<h1>Customer List</h1> <ul> <li *ngFor="let customer of observableCustomers | async"> {{ customer | json }} </li> </ul> |
-> result:
NgForOf with Local Variables
NgForOf
provides several exported values:
$implicit: T
-> Individual items’s value in the iterablengForOf: NgIterable
: -> The value of iterable expression.index: number
: -> index valuefirst: boolean
: ->true
if it is the first item.last: boolean
: ->true
if it is the last item.even: boolean
: ->true
if the item has an even index.odd: boolean
: ->true
if the item has an odd index.
All above exports can be aliased to local variables.
Practice :
-> Modify style file app.component.css
as below:
.even { color: blue; } .odd { color: goldenrod; } |
-> Modify template file app.component.html
as below:
<h1>Customer List</h1> <ul> <li *ngFor="let customer of observableCustomers | async; index as i; odd as odd; even as even" [ngClass]="{ odd: odd, even: even }"> {{i}} --- {{ customer | json }} </li> </ul> |
-> result:
Track By
Angular uses object identity to track insertions and deletions within the iterator and reproduce the changes in the DOM. Angular provides a way to customize the default tracking algorithm by trackBy
option. trackBy
takes a function with two arguments: index
and item
.
-> Syntax:
<li *ngFor="let item of items; index as i; trackBy: trackByFunction">...</li> |
Now, create a trackByFunction
function in AppComponent
class:
trackByFunction(index, customer) { return customer.id; } |
Add trackBy
to template file app.component.html
as below:
<h1>Customer List</h1> <ul> <li *ngFor="let customer of observableCustomers | async; index as i; odd as odd; even as even; trackBy as trackByFunction" [ngClass]="{ odd: odd, even: even }"> {{i}} --- {{ customer | json }} </li> </ul> |
What is the benefit of trackBy
option?
-> trackBy
returns a unique identifier that helps Angular to locate that DOM node associated with the object much faster, and reuse the component in the DOM which should it need to be updated (NOT destroy or rebuild).
trackBy
is used for performance optimization
Ng-Template element
To resolve the conflict between the template
tag and the html template
standard tag, Angular provides its own implementation: ng-template
tag.
Angular provides *
asterisk (*ngFor
) as a shorthand syntax for the ng-template
element. So the compiler will transform *ngFor
to ng-template
.
-> Syntax:
<ng-template ngFor let-item [ngForOf]="items" let-i="index" [ngForTrackBy]="trackByFn"> <li>...</li> </ng-template> |
Now, we modify the template file app.component.html
as below:
<ng-template ngFor let-customer [ngForOf]="observableCustomers | async" let-i="index" let-odd="odd" let-even="even" [ngForTrackBy]="trackByFunction"> <li [class.odd]="odd" [class.even]="even"> {{i}} --- {{ customer | json }} </li> </ng-template> |
SourceCode
How to run the below sourcecode:
1. Download Angular-6-NgFor.zip file -> Then extract it to Angular-6-NgFor folder. 2. Go to Angular-6-NgFor folder 3. Run the app by commandline: ng serve --open |
-> Source Code:
Last updated on April 19, 2019.