Привязать сортируемое значение индекса к модулю просмотра нокаута
У меня есть структура json, которая выглядит следующим образом, где "Позиция" является значением сортировки.
[
{"ID":1, "Title":"Title 1", "Position":1},
{"ID":2, "Title":"Title 2", "Position":2},
{"ID":5, "Title":"Title 3", "Position":3},
{"ID":7, "Title":"Title 4", "Position":99}
];
сортировка повыбыванию использует индекс для сортировки сортируемых предметов
Есть ли способ привязать это сортируемое значение индекса к моему свойству Position?
Вот jsFiddle моего кода.
По сути, когда элемент перетаскивается на новую позицию, я хочу обновить модуль просмотра, чтобы сохранить изменения в базе данных.
2 ответа
Для чего-то вроде этого я хотел бы добавить подписку к моему observableArray, которая берет один проход через массив и правильно устанавливает "индекс".
Вот расширение, которое будет работать для вашего варианта использования:
ko.observableArray.fn.withIndex = function(prop, startIndex, lastIndex) {
//by default use an "index" observable
prop = prop || "index";
//whenever the array changes, make a single pass through to update the indexes
this.subscribe(function(newValue) {
var item;
for (var i = 0, j = newValue.length; i < j; i++) {
//create the observable if it does not exist
item = newValue[i];
if (!item[prop]) {
item[prop] = ko.observable();
}
//special logic for the last one
item[prop]((lastIndex && i === (j - 1)) ? lastIndex : startIndex + i);
}
}, this);
return this;
};
Вы бы использовали это как:
myObservableArray.withIndex("Position", 1, 99);
Вот ваш обновленный образец: http://jsfiddle.net/rniemeyer/HVNUr/
Я добавил идентификатор в контейнер списка, чтобы я мог "слушать" модификацию dom, которая его изменяет. Я обертываю процесс обновления позиции в таймере, потому что событие модификации dom было запущено слишком много раз.
var positions = ko.utils.arrayMap(viewModel.Items(), function (item) {
return item.Position();
});
positions.sort();
var itmer = null;
$('#container').bind('DOMNodeInserted DOMNodeRemoved', function () {
if (itmer) clearTimeout(itmer);
itmer = setTimeout(function () {
var items = viewModel.Items();
ko.utils.arrayForEach(items, function (item) {
var index = $('#container [id=' + item.ID() + ']').last().index();
var newPosition = positions[index];
item.Position(newPosition);
});
}, 50);
});
Я надеюсь, что это помогает.