Knockout - Filtering, Sorting, and Paging
by Avinashullal
HTML
<script src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<b>Filters:</b><br />
<div data-bind="foreach: filter.filters">
<div>
<span data-bind="text: Name"></span>:<br />
</div>
<div data-bind="if: Type == 'select'">
<select data-bind="options: Options, optionsText: 'Name', value: CurrentOption"></select>
</div>
<div data-bind="if: Type == 'text'">
<input type="text" data-bind="value: Value, valueUpdate: 'afterkeydown'" />
</div>
</div>
<br />
<b>Sorts:</b>
Field:<br />
<select data-bind="options: sorter.sortOptions, optionsText: 'Name', value: sorter.currentSortOption"></select>
Direction:
<select data-bind="options: sorter.sortDirections, optionsText: 'Name', value: sorter.currentSortDirection"></select>
<br />
<br />
<div class="Pager"></div>
<div class="NoRecords"></div>
<table>
<thead>
<tr>
<th>
ID
</th>
<th>
Name
</th>
<th>
Status
</th>
</tr>
</thead>
<tbody data-bind="foreach: pager.currentPageRecords">
<tr>
<td>
<span data-bind="text: id"></span>
</td>
<td>
<span data-bind="text: name"></span>
</td>
<td>
<span data-bind="text: status"></span>
</td>
</tr>
</tbody>
</table>
CSS
.Pager
{
background-color: LightGray;
}
a
{
margin: 0px 5px;
}
JavaScript
function CustomerModel(data)
{
if (!data)
{
data = {};
}
var self = this;
self.id = data.id;
self.name = data.name;
self.status = data.status;
}
function CustomerPageModel(data)
{
if (!data)
{
data = {};
}
var self = this;
self.customers = ExtractModels(self, data.customers, CustomerModel);
var filters = [
{
Type: "text",
Name: "Name",
Value: ko.observable(""),
RecordValue: function(record) { return record.name; }
},
{
Type: "select",
Name: "Status",
Options: [
GetOption("All", "All", null),
GetOption("None", "None", "None"),
GetOption("New", "New", "New"),
GetOption("Recently Modified", "Recently Modified", "Recently Modified")
],
CurrentOption: ko.observable(),
RecordValue: function(record) { return record.status; }
}
];
var sortOptions = [
{
Name: "ID",
Value: "ID",
Sort: function(left, right) { return left.id < right.id; }
},
{
Name: "Name",
Value: "Name",
Sort: function(left, right) { return CompareCaseInsensitive(left.name, right.name); }
},
{
Name: "Status",
Value: "Status",
Sort: function(left, right) { return CompareCaseInsensitive(left.status, right.status); }
}
];
self.filter = new FilterModel(filters, self.customers);
self.sorter = new SorterModel(sortOptions, self.filter.filteredRecords);
self.pager = new PagerModel(self.sorter.orderedRecords);
}
function PagerModel(records)
{
var self = this;
self.pageSizeOptions = ko.observableArray([1, 5, 25, 50, 100, 250, 500]);
self.records = GetObservableArray(records);
self.currentPageIndex = ko.observable(self.records().length > 0 ? 0 : -1);
self.currentPageSize = ko.observable(25);
self.recordCount = ko.computed(function() {
return self.records().length;
});
self.maxPageIndex = ko.computed(function() {
return Math.ceil(self.records().length / self.currentPageSize()) - 1;
});
self.currentPageRecords = ko.computed(function() {
var newPageIndex = -1;
var pageIndex...