Created
April 16, 2014 13:01
-
-
Save sphingu/9d008d5cbc7bec8ae8ff to your computer and use it in GitHub Desktop.
Knockout Custom Pagination
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="body"> | |
<section class="content-wrapper main-content clear-fix" data-bind="with: personList" style="margin-top: 30px;"> | |
<table> | |
<thead> | |
<tr> | |
<td>First Name</td> | |
<td>Last Name</td> | |
<td>Age</td> | |
</tr> | |
</thead> | |
<tbody data-bind="foreach: items"> | |
<tr> | |
<td data-bind="text: FirstName"></td> | |
<td data-bind="text: LastName"></td> | |
<td data-bind="text: Age"></td> | |
</tr> | |
</tbody> | |
</table> | |
<div align="center"> | |
<ul class="pagination"> | |
<li><a href="#" data-bind="click: MoveFirst">««</a></li> | |
<li><a href="#" data-bind="click: MovePrev">«</a></li> | |
<li><span class="txt">Page <input style="width: 25px" type="text" data-bind="event: { blur: setCurrentPage }, value: page, valueUpdate: 'blur'" /> of <span data-bind="text: totalPages"></span></span></li> | |
<li><a href="#" data-bind="click: MoveNext">»</a></li> | |
<li><a href="#" data-bind="click: MoveLast">»»</a></li> | |
<li><span class="txt">Viewing <span data-bind="text:startingRecord"></span>- <span data-bind="text: endingRecord"></span> of <span data-bind="text: totalRowCount"></span></span></li> | |
</ul> | |
</div> | |
</section> | |
</div> | |
<script> | |
$(document).ready(function () { | |
var personViewModel = new PersonViewModel(); | |
ko.applyBindings(personViewModel, document.getElementById('body')); | |
}); | |
</script> | |
<style> | |
ul.pagination { | |
display: inline-block; | |
} | |
ul.pagination li { | |
display: inline; | |
} | |
ul.pagination li a, ul.pagination li span.txt { | |
padding: 2px 10px; | |
border: 1px solid #ddd; | |
background: aliceblue; | |
border-radius:2px; | |
} | |
ul.pagination li span.txt input { | |
text-align:center; | |
} | |
ul.pagination li a { | |
color:black; | |
text-decoration: none; | |
} | |
ul.pagination li a:hover { | |
background:#ddd; | |
text-decoration: underline; | |
} | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <reference path="jquery.d.ts" /> | |
/// <reference path="knockout.d.ts" /> | |
/// <reference path="knockout.validation.d.ts" /> | |
class PagedArray { | |
public items: KnockoutObservableArray<any>; | |
public totalRowCount: KnockoutObservable<number>; | |
public totalPages: KnockoutObservable<number>; | |
public pageIndex: KnockoutObservable<number>; | |
public page: KnockoutObservable<number>; | |
public pageSize: KnockoutObservable<number>; | |
public startingRecord: KnockoutComputed<number>; | |
public endingRecord: KnockoutComputed<number>; | |
//public pages: KnockoutComputed<number[]>; | |
//TODO : add Filter and Sorting Variables | |
public canMoveFirst: KnockoutComputed<boolean>; | |
public canMovePrev: KnockoutComputed<boolean>; | |
public canMoveNext: KnockoutComputed<boolean>; | |
public canMoveLast: KnockoutComputed<boolean>; | |
public MoveFirst: () => void; | |
public MovePrev: () => void; | |
public MoveNext: () => void; | |
public MoveLast: () => void; | |
public setCurrentPage: () => void; | |
public load: (success: any, fail: any) => void; | |
private reload: (success: (any, totalRowCount: number) => any, fail: (any) => any) => void; | |
private loader: (pageIndex: number, pageSize: number, success: (any, totalCount: number) => any, fail: (any) => any) => void; | |
constructor(loader: (pageIndex: number, pageSize: number, success: (any, totalRowCount: number) => any, fail: (any) => any) => void, pageSize) { | |
var self = this; | |
self.loader = loader; | |
self.pageIndex = ko.observable(0).extend({ notify: 'always' }); | |
self.page = ko.observable(1); | |
self.pageIndex.subscribe(function () { | |
self.page(self.pageIndex() + 1); | |
}) | |
self.pageSize = ko.observable(pageSize || 10); | |
self.items = ko.observableArray([]); | |
self.totalRowCount = ko.observable<number>(0); | |
self.totalPages = ko.computed(function () { | |
return Math.ceil(self.totalRowCount() / self.pageSize()); | |
}); | |
self.startingRecord = ko.computed(function () { | |
return self.pageIndex() * self.pageSize() + 1; | |
}); | |
self.endingRecord = ko.computed(function () { | |
return Math.min(self.page() * self.pageSize(), self.totalRowCount()); | |
}); | |
/*self.pages = ko.computed(function () { | |
var pageSlide = 2; | |
var pageCount = self.totalPages(); | |
var pageFrom = Math.max(1, +self.page() - pageSlide); | |
var pageTo = Math.min(pageCount, +self.page() + pageSlide); | |
pageFrom = Math.max(1, Math.min(pageTo - (2 * pageSlide), pageFrom)); | |
pageTo = Math.min(pageCount, Math.max(pageFrom + (2 * pageSlide), pageTo)); | |
var data = []; | |
for (var i = pageFrom; i <= pageTo; i++) { | |
data.push(i); | |
} | |
return data; | |
});*/ | |
/*<!--ko foreach: pages-- > | |
<!--ko if:$data == $parent.page()-- > | |
<li class="active" ><a href = "#" data - bind = "text: $data" ></a></li > | |
<!-- / ko-- > | |
<!--ko if:$data != $parent.page()-- > | |
<li><a href = "#" data - bind = "text: $data, click: function(){ $parent.page($data); $parent.setCurrentPage(); } " ></a></li > | |
<!-- / ko-- > | |
<!-- / ko-- >*/ | |
self.canMoveNext = ko.computed(function () { | |
return self.page() != self.totalPages(); | |
}); | |
self.canMovePrev = ko.computed(function () { | |
return self.page() != 1; | |
}); | |
self.canMoveFirst = ko.computed(function () { | |
return self.canMovePrev(); | |
}); | |
self.canMoveLast = ko.computed(function () { | |
return self.canMoveNext(); | |
}); | |
self.MoveNext = () => { | |
if (self.canMoveNext()) { | |
self.pageIndex(self.pageIndex() + 1); | |
self.reload(null, null); | |
} | |
}; | |
self.MovePrev = () => { | |
if (self.canMovePrev()) { | |
self.pageIndex(self.pageIndex() - 1); | |
self.reload(null, null); | |
} | |
}; | |
self.MoveLast = () => { | |
if (self.canMoveLast()) { | |
self.pageIndex(self.totalPages() - 1); | |
self.reload(null, null); | |
} | |
}; | |
self.MoveFirst = () => { | |
if (self.canMoveFirst()) { | |
self.pageIndex(0); | |
self.reload(null, null); | |
} | |
}; | |
//set page Index from page variable and reload data | |
self.setCurrentPage = () => { | |
if (isNaN(self.page())) { | |
self.page(self.pageIndex() + 1); | |
return; | |
} | |
var currentPage = +self.page(); | |
self.page(currentPage); | |
//return if given page is already current page | |
if (currentPage == self.pageIndex() + 1) { | |
return; | |
} | |
if (currentPage <= 1) { | |
self.pageIndex(0); | |
self.reload(null, null); | |
} | |
else if (currentPage >= self.totalPages()) { | |
self.pageIndex(self.totalPages() - 1); | |
self.reload(null, null); | |
} | |
else { | |
self.pageIndex(currentPage - 1); | |
self.reload(null, null); | |
} | |
}; | |
self.load = (success, fail) => { | |
self.pageIndex(0); | |
self.reload(success, fail); | |
}; | |
self.reload = (success: (any, totalRowCount: number) => any, fail: (any) => any) => { | |
self.loader(self.pageIndex(), self.pageSize(), | |
function (data, totalRowCount) { | |
self.totalRowCount(totalRowCount); | |
self.items(data); | |
if (success) { | |
success(data, totalRowCount); | |
} | |
}, function (error) { | |
if (fail) { fail(error); } | |
else { alert(error.errorText || "Error"); } | |
}); | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class PersonModel | |
{ | |
public PersonModel(List<Person> persons,int count) | |
{ | |
this.Persons = persons; | |
this.TotalCount = count; | |
} | |
public List<Person> Persons { get; set; } | |
public int TotalCount { get; set; } | |
} | |
public class Person | |
{ | |
public Person(int id, string firstName, string lastName, int age) | |
{ | |
this.Id = id; | |
this.FirstName = firstName; | |
this.LastName = lastName; | |
this.Age = age; | |
} | |
public int Id { get; set; } | |
public string FirstName { get; set; } | |
public string LastName { get; set; } | |
public int Age { get; set; } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class PersonController : ApiController | |
{ | |
private List<Person> _personList; | |
public List<Person> PersonList { get { return _personList; } } | |
public PersonController() | |
{ | |
_personList = new List<Person>(); | |
for (int i = 1; i < 1000; i++) | |
{ | |
_personList.Add(new Person(i, "Sumit " + i, "Hingu " + i, i + 10)); | |
} | |
} | |
// GET api/person | |
public PersonModel Get(int pageSize, int pageIndex) | |
{ | |
PersonModel model = new PersonModel(PersonList.Skip(pageSize * pageIndex).Take(pageSize).ToList(),PersonList.Count); | |
return model; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <reference path="PagedArray.ts" /> | |
/// <reference path="jquery.d.ts" /> | |
/// <reference path="knockout.d.ts" /> | |
/// <reference path="knockout.validation.d.ts" /> | |
class PersonViewModel { | |
personList: PagedArray; | |
constructor() { | |
var self = this; | |
self.personList = new PagedArray((pageIndex, pageSize, success, fail) => { | |
$.ajax("/api/person", { | |
cache: false, | |
type: 'GET', | |
data: { pageIndex: pageIndex, pageSize: pageSize } | |
}).done(function (data) { | |
success(data.Persons, data.TotalCount); | |
}).fail(function (error) { | |
alert('Error Occured'); | |
}); | |
}, 7); | |
self.personList.load(null, null); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Two Services
GetItems(pageSize,pageIndex): items
GetTotalItems: totalCount
Page Size: [ ] Page 1 of 20 << < max five pages > >> Total Records