<!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',
      'underscore':                 'npm:underscore@1.8.3'
    },
    // 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 * as _ from 'underscore';

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) {
        if (page < 1 || page > this.pager.totalPages) {
            return;
        }

        // 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';
import * as _ from 'underscore';

export class PagerService {
    getPager(totalItems: number, currentPage: number = 1, pageSize: number = 10) {
        // calculate total pages
        let totalPages = Math.ceil(totalItems / pageSize);

        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 = _.range(startPage, endPage + 1);

        // 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"
    }
]