Reputation: 2474
I am trying to implement that functionality on this demo: http://opensoul.org/2011/06/23/live-search-with-knockoutjs/
I managed to get everything working, but the demo uses a very old version of knockout. When I upgrade the knockout version the functionality breaks.
This is my updated code:
$(function() {
var assets = [
{id: "1", poster: "Pic010.jpg", name: "Mike", category: "category1", type: "Movie", popup: "1" },
{id: "2", poster: "Pic06.jpg", name: "James", category: "category2", type: "Movie", popup: "2" },
{id: "3", poster: "Pic04.jpg", name: "John", category: "category1", type: "Pop-up", popup: "3" },
{id: "4", poster: "Pic07.jpg", name: "Bob", category: "category2", type: "Pop-up", popup: "4" },
{id: "5", poster: "Pic011.jpg", name: "Mary", category: "category3", type: "Promo", popup: "5" }
];
var viewModel = {
assets: ko.observableArray(assets),
query: ko.observable(''),
search: function(value) {
viewModel.assets.removeAll();
for(var x in assets) {
if(assets[x].name.toLowerCase().indexOf(value.toLowerCase()) >= 0) {
viewModel.assets.push(assets[x]);
}
}
}
};
viewModel.query.subscribe(viewModel.search);
ko.applyBindings(viewModel);
});
The display:
<form action="#">
<input class="form-control" placeholder="Search…" type="search" name="q" data-bind="value: query, valueUpdate: 'keyup'" autocomplete="off">
</form>
<div class="content">
<table>
<tbody data-bind="foreach:assets">
<tr>
<td style="vertical-align: middle" data-bind="text: id"> </td>
<td><img data-bind="attr:{ src: '/manager/files/' + poster }" height="100px" /></td>
<td style="vertical-align: middle" data-bind="text: name"></td>
<td style="vertical-align: middle" data-bind="text: category"></td>
<td style="vertical-align: middle" data-bind="text: type"></td>
<td style="vertical-align: middle" data-bind="text: popup"></td>
<td class="actions" style="vertical-align: middle">
<a href="/Assets/edit/5" data-bind="attr:{ href: '/Assets/edit/' + id }"><i class="fa fa-pencil-square-o"></i></a>
<form data-bind="attr:{ action: '/Assets/delete/' + id, name: 'delete_' + id, id: 'delete_'+ id }" style="display:none;" method="post"><input type="hidden" name="_method" value="POST"></form>
<a href="#" ><i class="fa fa-trash-o"></i></a>
</td>
</tr>
</tbody>
</table>
</div>
here are examples, working with Knockout version 1.21: http://jsfiddle.net/7ZLdk/1/ example not working with version 3.0: http://jsfiddle.net/7ZLdk/2/
Upvotes: 0
Views: 62
Reputation: 139778
This behavior has been changed back in 2011: Updated remove and removeAll to modify their underlying arrays rather han creating new arrays
So now when you call removeAll
on an ko.observableArray
it removes the items form the underlying arrays, so in your case it empties your original assets
array.
A quick fix would be to clone the array when assigning to your ko.observableArray
:
assets: ko.observableArray(assets.slice(0)),
Demo JSFiddle.
A better and more modern solution would be to use a ko.computed
property and the arrayFilter
helper method to do the filtering:
assets: ko.computed(function () {
if (!viewModel.query())
return assets;
return ko.utils.arrayFilter(assets, function(item) {
return item.name.toLowerCase().indexOf(viewModel.query().toLowerCase()) >= 0;
});
}, null, {deferEvaluation: true})
Demo JSFiddle.
Upvotes: 3