Elian
Elian

Reputation: 75

KnockoutJS - Mapping and Extenders

I'm trying to implement some kind of undo feature in my project using KnockoutJS. For this purpose, I'm using this extender:

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;
};  

Then I apply the extender to an object into the viewModel:

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

And when I want to undo an action, I do this:

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

This is ok in order to get the old values, but the extend function in the observable is lost so new changes are not saved in the "states" stack.

Suggestions?

Thanks in advance, Elian.

Upvotes: 1

Views: 820

Answers (1)

Rango
Rango

Reputation: 3907

I think you should not create new model instance performing undo op, but just update observable properties of existing model:

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

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

Looks like your myViewModel has own context, so you have to modify my code to get correct ref to the model.

Upvotes: 2

Related Questions