ko.extenders.arrayExtensions = function(target, options) {
target.filter = function(search, property) {
return ko.computed(function() {
var searchValue = ko.unwrap(search);
var prop = ko.unwrap(property);
return ko.utils.arrayFilter(this(), function(item) {
if (prop) {
var itemProp = ko.unwrap(item[prop]);
return itemProp.toString().indexOf(searchValue) > -1;
}
else {
return item.indexOf(searchValue) > -1;
}
});
}, target).extend({ arrayExtensions: true });
};
target.orderBy = function (propertyName) {
return ko.computed(function() {
var propName = ko.unwrap(propertyName);
if (propName) {
return this().sort(function(a,b) {
var aProp = ko.unwrap(a[propName]);
var bProp = ko.unwrap(b[propName]);
return aProp < bProp ? -1 : aProp > bProp ? 1 : 0; });
}
else {
return this().sort();
}
}, target).extend({ arrayExtensions: true});
};
return target;
}
ko.extenders.formatting = function (target, options) {
if (options === "date") {
target.date = function(format) {
return ko.computed(function() {
return moment(this()).format(format);
}, target);
};
}
if (options === "currency") {
target.currency = function(symbol) {
return ko.computed(function() {
return accounting.formatMoney(this(), ko.unwrap(symbol));
}, target);
};
}
return target;
};
var Dude = function Dude(name, amount, date) {
this.name = ko.observable(name);
this.amount = ko.observable(amount).extend({ formatting: "currency" });
this.date = ko.observable(moment(date)).extend({ formatting: "date" });
};
var viewModel = {
dudes: ko.observableArray([
new Dude("hercules", 100, "7/16/2005"),
new Dude("rembrandt", 2000, "1/1/2013"),
new Dude("einstein", 666, "9/19/2013"),
new Dude("einbrandt", 3876, "7/4/1776")
]).extend({ arrayExtensions: true }),
search: ko.observable(""),
orderBy: ko.observable("name"),
};
ko.applyBindings(viewModel);
Name filter:
<input type="text" data-bind="value: search, valueUpdate: 'afterkeydown'" />
Order by:
<select data-bind="value: orderBy">
<option value="name">Name</option>
<option value="amount">Amount</option>
<option value="date">Date</option>
</select>
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Amount</th>
<th>Date</th>
</tr>
</thead>
<tbody data-bind="foreach: dudes.filter(search, 'name').orderBy(orderBy)">
<tr>
<td data-bind="text: name"></td>
<td data-bind="text: amount.currency()"></td>
<td data-bind="text: date.date('dddd MMMM Do YYYY')"></td>
</tr>
</tbody>
</table>
External resources loaded into this fiddle: