#javascript #knockout.js
#javascript #knockout.js
Вопрос:
Я пытаюсь реализовать эту функциональность в этой демонстрации: http://opensoul.org/2011/06/23/live-search-with-knockoutjs /
Мне удалось заставить все работать, но в демонстрации используется очень старая версия knockout. Когда я обновляю нокаутную версию, функциональность прерывается.
Это мой обновленный код:
$(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);
});
Отображение:
<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">amp;nbsp;</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>
вот примеры, работающие с версией Knockout 1.21: http://jsfiddle.net/7ZLdk/1 / пример, не работающий с версией 3.0: http://jsfiddle.net/7ZLdk/2 /
Ответ №1:
Это поведение было изменено еще в 2011 году: обновлены remove и removeAll для изменения их базовых массивов, а не для создания новых массивов
Итак, теперь, когда вы вызываете removeAll
an ko.observableArray
, он удаляет элементы из базовых массивов, поэтому в вашем случае он очищает ваш исходный assets
массив.
Быстрым решением было бы клонировать массив при назначении вашему ko.observableArray
:
assets: ko.observableArray(assets.slice(0)),
Демонстрационный JSFiddle.
Лучшим и более современным решением было бы использовать ko.computed
свойство и arrayFilter
вспомогательный метод для выполнения фильтрации:
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})
Демонстрационный JSFiddle.