Introduction
Through this article, you will learn using Angular2:
- how you can create a table with pagination
- how you can implement a search bar to filter the content of table.
Background
To better understand this article , it is preferable that you have a good knowledge’s on:
- Data Binding
- TypeScript
- Angular2
Using the Code
A) Prerequisite
Before you start coding, I recommend you to download Angular2 template from Angular 2 website: Angular2 Quick Start.
When you run the cmd tree command you should find the below folders tree :
B) Build Application
To constitute, this example you should first create Typescript classes that build the pagination and search logic.
**) Angular2 typescript classes
This section will describe steps that I follow to build the core of application in Typescript:
Create Product.ts
This class contains a list of attributes that describes a product object. it will be used to define an item on the 'productList
' array.
export class Product {
constructor(
public id : number,
public name : string,
public description : string
){
}
}
Create Data.ts
This file contains a declaration and the initialization of a JSON array named ‘productList
’ that will be used after to populate the Product List table in the HTML view.
‘productList
’ is an array of Product, that’s why we do the import of ‘Person
’ class.
import {Product} from './Product';
export var productList: Product[] = [
{"id": 1, "name": "juice 1", "description": "description 1"},
{"id": 2, "name": "juice 2", "description": "description 2"},
{"id": 3, "name": "juice 3", "description": "description 3"},
{"id": 4, "name": "juice 4", "description": "description 4"},
{"id": 5, "name": "juice 5", "description": "description 5"},
{"id": 6, "name": "juice 6", "description": "description 6"},
{"id": 7, "name": "juice 7", "description": "description 7"},
{"id": 8, "name": "juice 8", "description": "description 8"},
{"id": 9, "name": "juice 9", "description": "description 9"},
{"id": 10, "name": "orange 1", "description": "description 1"},
{"id": 11, "name": "orange 2", "description": "description 2"},
{"id": 12, "name": "orange 3", "description": "description 3"},
{"id": 13, "name": "orange 4", "description": "description 4"},
{"id": 14, "name": "orange 5", "description": "description 5"},
{"id": 15, "name": "orange 6", "description": "description 6"},
{"id": 16, "name": "orange 7", "description": "description 7"},
{"id": 17, "name": "orange 8", "description": "description 8"},
{"id": 18, "name": "orange 9", "description": "description 9"},
{"id": 19, "name": "orange 10", "description": "description 10"},
{"id": 20, "name": "orange 11", "description": "description 11"},
{"id": 21, "name": "orange 12", "description": "description 12"},
{"id": 22, "name": "orange 13", "description": "description 13"},
{"id": 23, "name": "orange 14", "description": "description 14"},
{"id": 24, "name": "orange 15", "description": "description 15"},
{"id": 25, "name": "orange 16", "description": "description 16"},
{"id": 26, "name": "orange 17", "description": "description 17"},
]
Create app.paginationComponent.ts
This the main class, it disposes of the HTML template with the required binding, also the implementation of the pagination and search logic.
First you need to import the needed *.ts classes to build the Pagination class.
Pagination class will contain attributes and functions that constitute entries of Product Table, pagination and search input. Also it will handle events received from user interface thanks to binding.
To implement the pagination and filter system, I used these:
filteredItems
attribute: is an array of ‘Product’ used to stock the result of the search process executed by ‘FilterByName’ function. pageSize
attribute : indicate the number of entries per page, pages
: is a maximum of Page numbers that can be displayed in pagination bar (it’s the size of ‘pagesIndex’ array). pageNumber
attribute : is the maximum number of page can we deduce from the ‘ProductList’ in terms of ‘pageSize’ value, currentIndex
attribute : is the index of the current selected page, items
attribute : the content of selected page, pagesIndex
attribute : have the series of numbers shown in the pagination bar. pageStart
attribute : this the start index page in the pagination bar. inputName
attribute : is used to search a new list of Product which the value of the attribute name for each one contains the text in ‘inputName’ . Constructor
method : initialize the ‘filterditems’ from ‘ProductList’, and the pagination. Init
method : used to calculate the pagination values, and update the view screen. FilterByName
method : this function return a list of Products which the text in ‘inputName’ is a substring of the Product name. The result will be inserted in ‘filteredItems’ List. refreshItems
method : refresh the content of table depending mainly on values of the following attributes : ‘currentIndex’ , ‘pageSize’ , 'pages' and 'pageStart' . prevPage
method : this function will decrease the selected page index (‘currentIndex’) by one, and will refresh the display. nextPage
method : this function will increase the selected page index (‘currentIndex’) by one, and will refresh the display. setPage
method : invoked when user select a number from pagination. It will modify the ‘currentIndex’ value and refresh the view.
import { Component, NgModule } from '@angular/core';
import {Product} from './Product';
import {productList} from './data';
@Component({
selector: 'my-pagination',
template: `
<div class="form-group">
<label>Filter </label>
<input type="text" id="inputName" [(ngModel)]="inputName"/>
<input type="button" (click)="FilterByName()" value="Apply"/>
</div>
<div class='row'>
<div class="panel panel-default">
<!-- Default panel contents -->
<div class='panel-heading'>Product List</div>
<div class='panel-body'>
<table class="table table-bordered table-condensed ">
<thead>
<th>Id</th>
<th>Name</th>
<th>Description</th>
</thead>
<tbody>
<tr *ngFor="let item of items">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.description}}</td>
</tr>
</tbody>
</table>
<div class="btn-toolbar" role="toolbar" style="margin: 0;">
<div class="btn-group">
<label style="margin-top:10px">Page {{currentIndex}}/{{pageNumber}}</label>
</div>
<div class="btn-group pull-right">
<ul class="pagination" >
<li [ngClass]="{'disabled': (currentIndex == 1 || pageNumber == 0)}" ><a (click)="prevPage()" href="#">Prev</a></li>
<li *ngFor="let page of pagesIndex" [ngClass]="{'active': (currentIndex == page)}">
<a (click)="setPage(page)" href="#" >{{page}}</a>
</li>
<li [ngClass]="{'disabled': (currentIndex == pageNumber || pageNumber == 0)}" ><a (click)="nextPage()" href="#">Next</a></li>
</ul>
</div>
</div>
</div>
</div>
`,
styles: ['.pagination { margin: 0px !important; }']
})
export class Pagination {
filteredItems : Product[];
pages : number = 4;
pageSize : number = 5;
pageNumber : number = 0;
currentIndex : number = 1;
items: Product[];
pagesIndex : Array<number>;
pageStart : number = 1;
inputName : string = '';
constructor( ){
this.filteredItems = productList;
this.init();
};
init(){
this.currentIndex = 1;
this.pageStart = 1;
this.pages = 4;
this.pageNumber = parseInt(""+ (this.filteredItems.length / this.pageSize));
if(this.filteredItems.length % this.pageSize != 0){
this.pageNumber ++;
}
if(this.pageNumber < this.pages){
this.pages = this.pageNumber;
}
this.refreshItems();
console.log("this.pageNumber : "+this.pageNumber);
}
FilterByName(){
this.filteredItems = [];
if(this.inputName != ""){
productList.forEach(element => {
if(element.name.toUpperCase().indexOf(this.inputName.toUpperCase())>=0){
this.filteredItems.push(element);
}
});
}else{
this.filteredItems = productList;
}
console.log(this.filteredItems);
this.init();
}
fillArray(): any{
var obj = new Array();
for(var index = this.pageStart; index< this.pageStart + this.pages; index ++) {
obj.push(index);
}
return obj;
}
refreshItems(){
this.items = this.filteredItems.slice((this.currentIndex - 1)*this.pageSize, (this.currentIndex) * this.pageSize);
this.pagesIndex = this.fillArray();
}
prevPage(){
if(this.currentIndex>1){
this.currentIndex --;
}
if(this.currentIndex < this.pageStart){
this.pageStart = this.currentIndex;
}
this.refreshItems();
}
nextPage(){
if(this.currentIndex < this.pageNumber){
this.currentIndex ++;
}
if(this.currentIndex >= (this.pageStart + this.pages)){
this.pageStart = this.currentIndex - this.pages + 1;
}
this.refreshItems();
}
setPage(index : number){
this.currentIndex = index;
this.refreshItems();
}
}
Update app.module.ts
You should update this file to import the Pagination component in order to be visible from index.html.
import { NgModule} from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule} from '@angular/platform-browser';
import { Pagination} from './app.paginationComponent';
@NgModule({
imports: [ BrowserModule,FormsModule ],
declarations: [ Pagination],
bootstrap: [ Pagination]
})
export class AppModule { }
Create index.html
This a HTML page, in which we will include all required js files and css styles to run the pagination component.
<html>
<head>
<title>Angular QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="./css/styles.css">
<link rel="stylesheet" href="./css/bootstrap.css">
<!-- 1. Load libraries -->
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<!-- 3. Display the application -->
<body>
<div class="container">
<div class=" row">
<h3>Angular2 : Table Pagination with search bar</h3>
</div>
<br>
<div class=" row">
<div class="col col-lg-6">
<my-pagination>Loading...</my-pagination>
</div>
</div>
</div>
</body>
</html>
**) Run the demo :
To run the Angular2 application, you should write the following cmd command-line in the root folder of your application :
- npm install : to install required modules (optionnal).
- npm start : to start the build of application.
Finally, if the demo run successfully, you should get the following render :
If user select a page number from pagination bar, than the display will be as follow:
If user enter 'Orange' text into the search bar and click on 'Apply' button, the search process will give:
References
Points of Interest
I hope that you appreciated this post. Try to download the source code and i'm waiting for your questions and comments.
History
- v1 06/11/2016 : Initial version