KnockoutJS — сопоставление и расширители

Я пытаюсь реализовать какую-то функцию отмены в своем проекте с помощью KnockoutJS. Для этой цели я использую этот расширитель:

ko.extenders.trackChange = function (target, track) {
    if (track) {
        target.isDirty = ko.observable(false);
        target.originalValue = target();
        target.subscribe(function (newValue) {

            // Push to "states" array a JS representation of the viewModel
            // so I can get a stack of changes
            states.push(ko.toJS(track.myViewModel));

            target.isDirty(newValue != target.originalValue);               
            target.originalValue = newValue;

        });
    }
    return target;
};  

Затем я применяю расширитель к объекту в модели представления:

this.myViewModel = {
    label: ko.observable("Label").extend({ trackChange: this });
}

И когда я хочу отменить действие, я делаю это:

ko.applyBindings(ko.mapping.fromJS(states[statesPointer]));

Это нормально для получения старых значений, но функция расширения в наблюдаемом объекте теряется, поэтому новые изменения не сохраняются в стеке «состояний».

Предложения?

Заранее спасибо, Элиан.


person Elian    schedule 03.05.2013    source источник


Ответы (1)


Я думаю, вам не следует создавать новый экземпляр модели, выполняющий операцию отменить, а просто обновить наблюдаемые свойства существующей модели:

// you do:
// ko.applyBindings(ko.mapping.fromJS(states[statesPointer]));

// I would do:
ko.mapping.fromJS(states[statesPointer], myViewModel);

Похоже, у вашего myViewModel есть собственный контекст, поэтому вам нужно изменить мой код, чтобы получить правильную ссылку на модель.

person Rango    schedule 03.05.2013
comment
Это сработало, но мне пришлось создать модель представления с отображением: this.myViewModel = ko.mapping.fromJS({ label: ko.observable(Label).extend({ trackChange: this }); } Это нормально? - person Elian; 03.05.2013
comment
Кроме того, когда я делаю сопоставление, удлинитель trackChange перестает работать. - person Elian; 03.05.2013
comment
Вы можете сначала создать объект с помощью плагина mapping, а затем применить расширитель к его свойствам. В результате вы получите объект, который можно обновить методом, упомянутым в моем ответе; расширитель должен работать и после обновления. Вы можете увидеть мою демонстрацию здесь: jsfiddle.net/ZCXeV - person Rango; 03.05.2013
comment
Большое спасибо за демонстрацию. Я попытался воспроизвести сценарий, но расширитель все еще отсутствует после обновления. Не могли бы вы проверить эту скрипку, пожалуйста? jsfiddle.net/AF494/1 - person Elian; 04.05.2013