I know I know, Knockout JS is something considered obsolete, but I loved it, so I decided right to write two posts about it to share some snippets I developed, maybe someone will find it useful. So the first post is about a simple paginator, the first snippet is the core of the paginator and you can put it in a common javascript (eg Custom.Utility.js), as you can see it behaviors as a plugin for knockout.
// Knockout utilities if (typeof ko !== "undefined") { ko.bindingHandlers.fadeVisible = { init: function (element, valueAccessor) { $(element).fadeIn(); }, update: function (element, valueAccessor) { // Whenever the value subsequently changes, slowly fade the element in or out var value = valueAccessor(); ko.unwrap(value) ? $(element).fadeIn() : $(element).fadeOut(); } }; ko.safeObservable = function (initialValue) { var result = ko.observable(initialValue); result.safe = ko.dependentObservable(function () { return result() || {}; }); return result; }; ko.Paginator = function (observableValue) { var p = new Object(); p.PageSize = ko.observable(10); p.PageIndex = ko.observable(0); p.PagesToShowSize = ko.observable(5); p.PagedItemsLength = ko.observable(0); p.IsVisible = ko.dependentObservable(function () { var length = observableValue().length; return (length > p.PageSize()); }); p.PagedList = ko.dependentObservable(function () { var size = p.PageSize(); var start = p.PageIndex() * size; return observableValue().slice(start, start + size); }); p.MaxPageIndex = ko.dependentObservable(function () { var l = observableValue().length; if (p.PagedItemsLength() !== l) { p.PagedItemsLength(l); p.PageIndex(0); } return Math.ceil(p.PagedItemsLength() / p.PageSize()) - 1; }); p.PreviousPage = function () { var prev = p.PageIndex() - 1; if (p.PageIndex() > 0) { p.PageIndex(prev); p.MinPageRelativeIndex(prev); } }; p.NextPage = function () { var next = p.PageIndex() + 1; if (p.PageIndex() < p.MaxPageIndex()) { p.PageIndex(next); p.MinPageRelativeIndex(next); } }; p.MinPageRelativeIndex = ko.observable(0); p.MaxPageRelativeIndex = ko.dependentObservable(function () { var relativeMax = p.MinPageRelativeIndex() + p.PagesToShowSize(); if (relativeMax > p.MaxPageIndex()) { var min = p.MaxPageIndex() - p.PagesToShowSize(); p.MinPageRelativeIndex(min < 0 ? 0 : min); relativeMax = p.MaxPageIndex() + 1; } return relativeMax; }); p.PagesToShow = ko.dependentObservable(function () { var pages = []; var minValue = p.MinPageRelativeIndex(); var maxValue = p.MaxPageRelativeIndex(); for (i = minValue; i < maxValue; i++) { pages.push({ PageNumber: (i + 1) }); } return pages; }); p.MoveToPage = function (index) { p.PageIndex(index); }; return p; }; } else { console.log("Knockout not imported... cannot decorate with new functions") }This second snippet is the declaration of the paginator in the HTML page, as you can see I refer to Custom.ViewModel as the namespace of the javascript. In the DIV class=”items” you are free to implement your preferred view, while in the DIV class=”paginator” you simply have to refer to the correct namespace.
Last but not least this is the initialization all the component in the Knockout controller....
// View model definition controller.ViewModel = function ViewModel() { var vm = this; vm.Paginator = ko.Paginator(vm.Items); ... };