Thursday, February 20, 2014

Pagination with Knockout & JQuery

Oftern times, when we need to render large data sets on a web page, we must use pagination or something similar (think of twitter or facebook - load when scrolled down). Today, I'm going to show you how to create pagination with JQuery, Knockout.JS and a pretty cool jquery plugin, "Simple Pagination".

download the "Simple Pagination" JQuery plugin here.

Assume you have an API which return data something like this (orders in my case)

    "Items": [
          "ID": 12, 
          "Description": "New pair of shoes", 
          "InvoiceDate": "2012-08-16T00:00:00" 
          "ID": 13, 
          "Description": "One bottle of Juise", 
          "InvoiceDate": "2012-09-16T00:00:00" 
      [Upto 10 Items]
    "TotalCount": 38,
    "CurrentPage": 1,
    "PageSize": 10,
    "PageCount": 4

I have a ViewModel and a Model to match these data. Something like this... (javascript)

(function (itb) {
    var OrdersModel = function (id,desc,idate) {

        var self = this;

        self.ID = ko.observable(id);
        self.Description = ko.observable(desc);
        self.InvoiceDate = ko.observable(idate);
    itb.OrdersModel = OrdersModel;

and a ViewModel for "business logic". Code is self explanatory, if don't understand, please mention in comments, I will try my best to explain.

(function (itb) {
    var OrdersViewModel = function () {

        var self = this;

        self.currentPage = ko.observable(1);
        self.pageCount = ko.observable(1);
        self.pageSize = ko.observable(10);
        self.totalCount = ko.observable(1);

        self.orders = ko.observableArray();

        self.loadSuccess = function (data) {

            // Clear the orders array

            // Set the pagining related data from JSON

            // Loop through items in JSON, 
            // Create new order model and push it into the Items array
            // NOTE: you can use array map utilities in knockout too
            for (var i = 0; i < data.Items.length; i++) {
                var cu = data.Items[i];

                var newItem = new AwesomeSystem.OrdersModel(cu.ID, cu.Description, cu.InvoiceDate);


            // Lets create pagination for this data

        self.loadFailed = function (result) {
            alert("load failed");

        self.initialize = function () {

        // my api urs for paged data looks like
        // http://mysite/api/orders/{pageNo}/{pageSize}
        self.getOrdersAJAX = function (pageNo, pageSize) {
            var url = 'api/orders/';

            if (pageNo > 1)
                url += pageNo + "/" + pageSize;

            $.get(url, null, self.loadSuccess, self.loadFailed);
        // load the given page 
        self.loadPage = function (pageNo, event) {
            self.getOrdersAJAX(pageNo, self.pageSize());

        self.createPagination = function () {
            // pagination source:
                pages: self.pageCount(),
                itemsOnPage: self.pageSize(),
                currentPage: self.currentPage(),
                cssStyle: 'pagination',
                onPageClick: self.loadPage // fires when a page is clicked 


    itb.OrdersViewModel = OrdersViewModel;

And, we have the Markup like this.

<table class="table table-bordered table-striped table-hover">
                <th>Invoice Date</th>
        <tbody data-bind="foreach: orders">

                    <span data-bind="text: Description"></span>
                    <span data-bind="text: InvoiceDate"></span>


    <!-- // Table END -->
   <ul id="paginationHolder"></ul>

Lastly apply the bindings.

<script src="~/Scripts/plugins/jquery/jquery.simplePagination.js"></script>
    var viewModel = new AwesomeSystem.OrdersViewModel();