Свързване на сортируема индексна стойност към нокаут изгледен модул

Имам 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}
];

knockout-sortable използва индекс за сортиране на сортируеми елементи

Има ли начин да обвържа тази сортируема индексна стойност към моето свойство Position?

Ето jsFiddle от моя код.

По принцип, когато даден елемент се плъзне на нова позиция, искам да актуализирам viewmodule, така че да мога да запазя промяната обратно в базата данни.


person Brad Bamford    schedule 22.06.2013    source източник


Отговори (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/

person RP Niemeyer    schedule 22.06.2013
comment
Това е красиво! Той прави точно това, което трябва да прави, и го прави по нокаутиращия начин. - person Brad Bamford; 22.06.2013
comment
Ето леко актуализиран jsFiddle, който също така включва корекция за проблема isDirty. - person Brad Bamford; 24.06.2013

Добавих идентификационен номер към контейнера на списъка, за да мога да "слушам" модификация на 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);

});

Вижте цигулка

Надявам се да помогне.

person Damien    schedule 22.06.2013
comment
Трябва да призная, че успяхте да накарате това да работи по начини, за които не се сетих. Въпреки това отговорът на RP Niemeyer по-долу изглежда по-чист и ще работи във всички браузъри. - person Brad Bamford; 22.06.2013