I´m creating a sortable table using Knockout. The table binding, the sorting functionality and Filtering is Working fine. However, I´d like to show a sorting icon when a specific column is active.
Since the span has bind to visible property in the header array, and this property is observable, when this value changes (in the sort function), the UI should update, but is not. What could be causing this?
Here is the JSFiddle: http://jsfiddle.net/ud3o79ag/1/
HTML:
<form action="#">
<input class="form-control" placeholder="Buscar…" type="search" name="q" data-bind="value: query, valueUpdate: 'keyup'" autocomplete="off">
</form>
<table class="table table-bordered table-striped">
<thead>
<tr data-bind="foreach: headers">
<th data-bind="click: $parent.sort">
<span data-bind="text: title"></span>
<span class="glyphicon glyphicon-sort-by-alphabet" data-bind="visible:active"></span>
</th>
</tr>
</thead>
<tbody data-bind="name:author, foreach:authors">
<tr>
<td data-bind="text:FirstName"></td>
<td data-bind="text:LastName"></td>
<td data-bind="text:Biography"></td>
<td></td>
</tr>
</tbody>
</table>
JS/Knockout:
var viewModel = function()
{
var self = this;
self.query = ko.observable('');
self.headers = [
{title:'First Name',sortPropertyName:'FirstName', asc: true, active: ko.observable(false)},
{title:'Last Name',sortPropertyName:'LastName', asc: true, active: ko.observable(false)},
{title:'Biography',sortPropertyName:'Biography', asc: true, active: ko.observable(false)},
{title:'Actions',sortPropertyName:'', asc: true, active: ko.observable(false)}
];
self.activeSort = ko.observable(function(){return 0;});
self.sort = function(header,event)
{
//if this header was just clicked a second time
if(header.active) {
header.asc = !header.asc; //toggle the direction of the sort
}
//make sure all other headers are set to inactive
ko.utils.arrayForEach(self.headers, function(item){ item.active = false; } );
//the header that was just clicked is now active
header.active = true;//our now-active header
var prop = header.sortPropertyName;
var ascSort = function(a,b){ return a[prop] < b[prop] ? -1 : a[prop] > b[prop] ? 1 : a[prop] == b[prop] ? 0 : 0;};
var descSort = function(a,b){ return a[prop] > b[prop] ? -1 : a[prop] < b[prop] ? 1 : a[prop] == b[prop] ? 0 : 0;};
var sortFunc = header.asc ? ascSort : descSort;
//store the new active sort function
self.activeSort(sortFunc);
};
self.authors = ko.computed(function() {
var search = self.query().toLowerCase();
var result;
var arrayresult;
if (!search)
{
result = authors;
}
else
{
result = ko.utils.arrayFilter(authors, function(item) {
if (item['FirstName'].toLowerCase().indexOf(search) >= 0 || item.LastName.toLowerCase().indexOf(search) >= 0)
{
return true;
}
else
{
return false;
}
});
}
arrayresult = [].slice.call(result).sort(self.activeSort());
return arrayresult;
});
};
ko.applyBindings(new viewModel);
Look here: http://jsfiddle.net/ud3o79ag/6/
You must set an observable using a function, so use this:
instead of this:
Btw I have added an "X" to your indicator, so you can actually see it.