I'm new to knockout js & need help workout how to dynamically sort a table using the column header.
Following is part of my code:
HTML:
<table>
<thead>
<tr data-bind="click: sortFunction">
<th id='id'>Id</th>
<th id='name'>Name</th>
<th id='description'>Description</th>
</tr>
</thead>
<tbody data-bind="foreach: deptList">
<tr>
<td><span data-bind="text: id" /></td>
<td><span data-bind="text: name" /></td>
<td><span data-bind="text: description" /></td>
</tr>
</tbody>
</table>
In my view model I've the following function which I use to sort a data table using the table header.
ViewModel:
self.deptList = ko.observableArray(mylist);
self.sortColumn = ko.observable("id");
self.isSortAsc = ko.observable("True");
var Dept = function(id, name, description) {
this.id = ko.observable(id);
this.name = ko.observable(name);
this.description = ko.observable(description);
};
var mylist = [
new Dept(1, "Dept 1", "D1"),
new Dept(2, "Dept 2", "D6"),
new Dept(3, "Dept 3", "D3"),
new Dept(4, "Dept 4", "D4")
];
self.sortFunction = function(data, event) {
if (self.sortColum === event.target.id)
self.isSortAsc = !self.isSortAsc;
else {
self.sortColumn = event.target.id;
self.isSortAsc = "True";
}
self.deptList.sort(function(a, b) {
if (self.sortColum === 'id') {
if (self.isSortAsc)
a.id < b.id ? -1 : 1;
else
a.name < b.name ? 1 : -1;
} else if (self.sortColum === 'name') {
if (self.isSortAsc)
a.name < b.name ? -1 : 1;
else
a.name < b.name ? 1 : -1;
} else(self.sortColum === 'description') {
if (self.isSortAsc)
a.description < b.description ? -1 : 1;
else
a.description < b.description ? 1 : -1;
}
});
};
Even though above code is working I think there should be a better way to do this (I mean passing the column id as a parameter) which will be useful when there is a large of columns.
I tried left[self.sortColumn] < right[self.sortColumn] ? -1 : 1
, which didn't work as expected.
If it is possible to sort via a dynamic column name please show a sample code.
Thanks in advance.
Here is a quick bindingHandler that you can add to your th's. Upon clicking the th it will sort the column according the property name as defined in the binding.
ko.bindingHandlers.sort = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var asc = false;
element.style.cursor = 'pointer';
element.onclick = function(){
var value = valueAccessor();
var prop = value.prop;
var data = value.arr;
asc = !asc;
data.sort(function(left, right){
var rec1 = left;
var rec2 = right;
if(!asc) {
rec1 = right;
rec2 = left;
}
var props = prop.split('.');
for(var i in props){
var propName = props[i];
var parenIndex = propName.indexOf('()');
if(parenIndex > 0){
propName = propName.substring(0, parenIndex);
rec1 = rec1[propName]();
rec2 = rec2[propName]();
} else {
rec1 = rec1[propName];
rec2 = rec2[propName];
}
}
return rec1 == rec2 ? 0 : rec1 < rec2 ? -1 : 1;
});
};
}
};
This is a little more elegant in that you don't have to create a separate function for each column. A more complete working example can be found here: http://jsfiddle.net/brendonparker/6S85t/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With