<!DOCTYPE html>
<html>
<head>
<base href="./" />
<title>Angular 2 Pagination Example with Logic like Google</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- bootstrap css -->
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<!-- application css -->
<link href="app.css" rel="stylesheet" />
<!-- polyfill(s) for older browsers -->
<script src="https://unpkg.com/core-js/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js@0.6.25?main=browser"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.8"></script>
<script src="https://unpkg.com/systemjs@0.19.39/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
</head>
<body>
<app>Loading...</app>
</body>
</html>
/**
* WEB ANGULAR VERSION
* (based on systemjs.config.js in angular.io)
* System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
// DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
transpiler: 'ts',
typescriptOptions: {
// Complete copy of compiler options in standard tsconfig.json
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"../../node_modules/@types/"
]
},
meta: {
'typescript': {
"exports": "ts"
}
},
paths: {
// paths serve as alias
'npm:': 'https://unpkg.com/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'@angular/common': 'npm:@angular/common@2.2.1/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler@2.2.1/bundles/compiler.umd.js',
'@angular/core': 'npm:@angular/core@2.2.1/bundles/core.umd.js',
'@angular/forms': 'npm:@angular/forms@2.2.1/bundles/forms.umd.js',
'@angular/http': 'npm:@angular/http@2.2.1/bundles/http.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser@2.2.1/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic@2.2.1/bundles/platform-browser-dynamic.umd.js',
'@angular/router': 'npm:@angular/router@3.2.1/bundles/router.umd.js',
// other libraries
'rxjs': 'npm:rxjs@5.0.0-rc.3',
'ts': 'npm:plugin-typescript@4.0.10/lib/plugin.js',
'typescript': 'npm:typescript@2.0.3/lib/typescript.js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
rxjs: {
defaultExtension: 'js'
}
}
});
if (!global.noBootstrap) { bootstrap(); }
// Bootstrap the `AppModule`(skip the `app/main.ts` that normally does this)
function bootstrap() {
// Stub out `app/main.ts` so System.import('app') doesn't fail if called in the index.html
System.set(System.normalizeSync('app/main.ts'), System.newModule({ }));
// bootstrap and launch the app (equivalent to standard main.ts)
Promise.all([
System.import('@angular/platform-browser-dynamic'),
System.import('app/app.module')
])
.then(function (imports) {
var platform = imports[0];
var app = imports[1];
platform.platformBrowserDynamic().bootstrapModule(app.AppModule);
})
.catch(function(err){ console.error(err); });
}
})(this);
a {
cursor: pointer;
}
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
import { Component, OnInit } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map'
import { PagerService } from './_services/index'
@Component({
moduleId: module.id,
selector: 'app',
templateUrl: 'app.component.html'
})
export class AppComponent implements OnInit {
constructor(private http: Http, private pagerService: PagerService) { }
// array of all items to be paged
private allItems: any[];
// pager object
pager: any = {};
// paged items
pagedItems: any[];
ngOnInit() {
// get dummy data
this.http.get('./dummy-data.json')
.map((response: Response) => response.json())
.subscribe(data => {
// set items to json response
this.allItems = data;
// initialize to page 1
this.setPage(1);
});
}
setPage(page: number) {
// get pager object from service
this.pager = this.pagerService.getPager(this.allItems.length, page);
// get current page of items
this.pagedItems = this.allItems.slice(this.pager.startIndex, this.pager.endIndex + 1);
}
}
<div>
<div class="container">
<div class="text-center">
<h1>Angular 2 - Pagination Example with logic like Google</h1>
<!-- items being paged -->
<div *ngFor="let item of pagedItems">{{item.name}}</div>
<!-- pager -->
<ul *ngIf="pager.pages && pager.pages.length" class="pagination">
<li [ngClass]="{disabled:pager.currentPage === 1}">
<a (click)="setPage(1)">First</a>
</li>
<li [ngClass]="{disabled:pager.currentPage === 1}">
<a (click)="setPage(pager.currentPage - 1)">Previous</a>
</li>
<li *ngFor="let page of pager.pages" [ngClass]="{active:pager.currentPage === page}">
<a (click)="setPage(page)">{{page}}</a>
</li>
<li [ngClass]="{disabled:pager.currentPage === pager.totalPages}">
<a (click)="setPage(pager.currentPage + 1)">Next</a>
</li>
<li [ngClass]="{disabled:pager.currentPage === pager.totalPages}">
<a (click)="setPage(pager.totalPages)">Last</a>
</li>
</ul>
</div>
</div>
<hr />
<div class="credits text-center">
<p>
<a href="http://jasonwatmore.com/post/2016/08/23/angular-2-pagination-example-with-logic-like-google" target="_top">Angular 2 - Pagination Example with logic like Google</a>
</p>
<p>
<a href="http://jasonwatmore.com" target="_top">JasonWatmore.com</a>
</p>
</div>
</div>
export * from './pager.service';
export class PagerService {
getPager(totalItems: number, currentPage: number = 1, pageSize: number = 10) {
// calculate total pages
let totalPages = Math.ceil(totalItems / pageSize);
// ensure current page isn't out of range
if (currentPage < 1) {
currentPage = 1;
} else if (currentPage > totalPages) {
currentPage = totalPages;
}
let startPage: number, endPage: number;
if (totalPages <= 10) {
// less than 10 total pages so show all
startPage = 1;
endPage = totalPages;
} else {
// more than 10 total pages so calculate start and end pages
if (currentPage <= 6) {
startPage = 1;
endPage = 10;
} else if (currentPage + 4 >= totalPages) {
startPage = totalPages - 9;
endPage = totalPages;
} else {
startPage = currentPage - 5;
endPage = currentPage + 4;
}
}
// calculate start and end item indexes
let startIndex = (currentPage - 1) * pageSize;
let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1);
// create an array of pages to ng-repeat in the pager control
let pages = Array.from(Array((endPage + 1) - startPage).keys()).map(i => startPage + i);
// return object with all pager properties required by the view
return {
totalItems: totalItems,
currentPage: currentPage,
pageSize: pageSize,
totalPages: totalPages,
startPage: startPage,
endPage: endPage,
startIndex: startIndex,
endIndex: endIndex,
pages: pages
};
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { PagerService } from './_services/index';
@NgModule({
imports: [
BrowserModule,
HttpModule
],
declarations: [
AppComponent
],
providers: [
PagerService
],
bootstrap: [AppComponent]
})
export class AppModule { }
[
{
"name": "Item 1"
},
{
"name": "Item 2"
},
{
"name": "Item 3"
},
{
"name": "Item 4"
},
{
"name": "Item 5"
},
{
"name": "Item 6"
},
{
"name": "Item 7"
},
{
"name": "Item 8"
},
{
"name": "Item 9"
},
{
"name": "Item 10"
},
{
"name": "Item 11"
},
{
"name": "Item 12"
},
{
"name": "Item 13"
},
{
"name": "Item 14"
},
{
"name": "Item 15"
},
{
"name": "Item 16"
},
{
"name": "Item 17"
},
{
"name": "Item 18"
},
{
"name": "Item 19"
},
{
"name": "Item 20"
},
{
"name": "Item 21"
},
{
"name": "Item 22"
},
{
"name": "Item 23"
},
{
"name": "Item 24"
},
{
"name": "Item 25"
},
{
"name": "Item 26"
},
{
"name": "Item 27"
},
{
"name": "Item 28"
},
{
"name": "Item 29"
},
{
"name": "Item 30"
},
{
"name": "Item 31"
},
{
"name": "Item 32"
},
{
"name": "Item 33"
},
{
"name": "Item 34"
},
{
"name": "Item 35"
},
{
"name": "Item 36"
},
{
"name": "Item 37"
},
{
"name": "Item 38"
},
{
"name": "Item 39"
},
{
"name": "Item 40"
},
{
"name": "Item 41"
},
{
"name": "Item 42"
},
{
"name": "Item 43"
},
{
"name": "Item 44"
},
{
"name": "Item 45"
},
{
"name": "Item 46"
},
{
"name": "Item 47"
},
{
"name": "Item 48"
},
{
"name": "Item 49"
},
{
"name": "Item 50"
},
{
"name": "Item 51"
},
{
"name": "Item 52"
},
{
"name": "Item 53"
},
{
"name": "Item 54"
},
{
"name": "Item 55"
},
{
"name": "Item 56"
},
{
"name": "Item 57"
},
{
"name": "Item 58"
},
{
"name": "Item 59"
},
{
"name": "Item 60"
},
{
"name": "Item 61"
},
{
"name": "Item 62"
},
{
"name": "Item 63"
},
{
"name": "Item 64"
},
{
"name": "Item 65"
},
{
"name": "Item 66"
},
{
"name": "Item 67"
},
{
"name": "Item 68"
},
{
"name": "Item 69"
},
{
"name": "Item 70"
},
{
"name": "Item 71"
},
{
"name": "Item 72"
},
{
"name": "Item 73"
},
{
"name": "Item 74"
},
{
"name": "Item 75"
},
{
"name": "Item 76"
},
{
"name": "Item 77"
},
{
"name": "Item 78"
},
{
"name": "Item 79"
},
{
"name": "Item 80"
},
{
"name": "Item 81"
},
{
"name": "Item 82"
},
{
"name": "Item 83"
},
{
"name": "Item 84"
},
{
"name": "Item 85"
},
{
"name": "Item 86"
},
{
"name": "Item 87"
},
{
"name": "Item 88"
},
{
"name": "Item 89"
},
{
"name": "Item 90"
},
{
"name": "Item 91"
},
{
"name": "Item 92"
},
{
"name": "Item 93"
},
{
"name": "Item 94"
},
{
"name": "Item 95"
},
{
"name": "Item 96"
},
{
"name": "Item 97"
},
{
"name": "Item 98"
},
{
"name": "Item 99"
},
{
"name": "Item 100"
},
{
"name": "Item 101"
},
{
"name": "Item 102"
},
{
"name": "Item 103"
},
{
"name": "Item 104"
},
{
"name": "Item 105"
},
{
"name": "Item 106"
},
{
"name": "Item 107"
},
{
"name": "Item 108"
},
{
"name": "Item 109"
},
{
"name": "Item 110"
},
{
"name": "Item 111"
},
{
"name": "Item 112"
},
{
"name": "Item 113"
},
{
"name": "Item 114"
},
{
"name": "Item 115"
},
{
"name": "Item 116"
},
{
"name": "Item 117"
},
{
"name": "Item 118"
},
{
"name": "Item 119"
},
{
"name": "Item 120"
},
{
"name": "Item 121"
},
{
"name": "Item 122"
},
{
"name": "Item 123"
},
{
"name": "Item 124"
},
{
"name": "Item 125"
},
{
"name": "Item 126"
},
{
"name": "Item 127"
},
{
"name": "Item 128"
},
{
"name": "Item 129"
},
{
"name": "Item 130"
},
{
"name": "Item 131"
},
{
"name": "Item 132"
},
{
"name": "Item 133"
},
{
"name": "Item 134"
},
{
"name": "Item 135"
},
{
"name": "Item 136"
},
{
"name": "Item 137"
},
{
"name": "Item 138"
},
{
"name": "Item 139"
},
{
"name": "Item 140"
},
{
"name": "Item 141"
},
{
"name": "Item 142"
},
{
"name": "Item 143"
},
{
"name": "Item 144"
},
{
"name": "Item 145"
},
{
"name": "Item 146"
},
{
"name": "Item 147"
},
{
"name": "Item 148"
},
{
"name": "Item 149"
},
{
"name": "Item 150"
}
]