knockout pagination

knockout pagination

by Dejan Vasic

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.6/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.3.7/js/tether.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"></script>
<div class="container">
  <h2>
  paged
</h2>
  <p>
    current <span data-bind="text: currentPage"></span>
  </p>
  <div data-bind="foreach: ticketsFiltered">
    <div>
      <label data-bind="text: ticketName"></label>
    </div>
  </div>

  <div data-bind="component: { name: 'pagination', params: {totalItems: tickets().length, changePage: viewPage, maxPagesToDisplay: 6, pageSize: 2}}">

  </div>

</div>

JavaScript

var data = [{
  ticketName: 'general',
}, {
  ticketName: 'child',
}, {
  ticketName: 'hello',
}, {
  ticketName: 'world',
}, {
  ticketName: 'foo',
}, {
  ticketName: 'bar',
}, {
  ticketName: 'h1',
}, {
  ticketName: 'h2',
}, {
  ticketName: 'h3',
}, {
  ticketName: 'h4',
}, {
  ticketName: 'h5',
}, {
  ticketName: 'h6',
}, {
  ticketName: 'h7'
}, {
  ticketName: 'h8'
}, {
  ticketName: 'h9'
}];

function FindTickets(data) {
  var pageSize = 2;
  var me = this;
  me.tickets = ko.observableArray();
  _.each(data, function(t) {
    me.tickets.push(new Ticket(t));
  });

  me.currentPage = ko.observable(1);
  me.ticketsFiltered = ko.computed(function() {
    var chunked = _.chunk(data, pageSize);
    return chunked[me.currentPage() - 1];
  });

  me.viewPage = function(pageNum) {
    me.currentPage(pageNum);
  }
}

function Ticket(data) {
  var me = this;
  me.ticketName = ko.observable(data.ticketName);
}

ko.components.register('pagination', {
  viewModel: function(param) {
    var me = this;
    me.currentPage = ko.observable(1);
    me.pages = ko.observableArray();
    me.totalPages = ko.observable(Math.ceil(param.totalItems / param.pageSize));

    for (var i = 0; i <= param.totalItems; i++) {
      this.pages.push(new Page({
        number: i + 1,
        selectPage: function(pageNum) {
          me.currentPage(pageNum);
          if (param.changePage) {
            param.changePage(pageNum);
          }
        }
      }));
    }

    this.pagesFiltered = ko.computed(function() {
      var current = me.currentPage();
      var max = param.maxPagesToDisplay;
      var total = me.totalPages();

      // Calculate start page
      var start = (current - max) + 1;
      if (start <= 0) {
        start = 1;
      }

      var end = start + (max - 1);

      // Calculate end page 
      if (current === total) {
        end = current;
      }

      if (current === end && current < total) {
        end += 1;
        start += 1;
      }

      // Slice method is...