-1

In order to do optimistic concurrency checking when posting/saving back the (possibly) modified view model to the server, I would like to take a copy of the original value in a separate variable than the observable one I bind to with knockout bindings.

Is this possible to do with the knockout mapping plugin, or do I have to iterate over the mapped observables to take a copy after I've populated the view model?

larsw
  • 3,790
  • 2
  • 25
  • 37

1 Answers1

0

How about this?

function Task(data) {
    var self = this;
    self.title = ko.observable(data.title);
    self.origTitle = data.title;
    self.isDone = ko.observable(data.isDone);
    self.origIsDone = data.isDone;

    self.changes = ko.computed(function() {
        var changed = [];

        if (self.title() != self.origTitle) changed.push({ self.title(), self.origTitle });
        if (self.isDone() != self.origIsDone) changed.push({ self.isDone(), self.origIsDone });
        return changed;
    });
}

function TaskListViewModel() {
    // Data
    var self = this;
    self.tasks = ko.observableArray([]);
    self.newTaskText = ko.observable();
    self.changes = ko.computed(function() {
        var tasksToPost = ko.utils.arrayFilter(self.tasks(), function(task) { return task.changed().length > 0 });            
        $.ajax({
            type: 'POST',
            url: '/SomeUrl',
            data: tasksToPost 
        });
    });

    // Operations
    self.addTask = function() {
        self.tasks.push(new Task({ title: this.newTaskText() }));
        self.newTaskText("");
    };
    self.removeTask = function(task) { self.tasks.remove(task) };

    // Load initial state from server, convert it to Task instances, then populate self.tasks
    $.getJSON("/tasks", function(allData) {
        var mappedTasks = $.map(allData, function(item) { return new Task(item) });
        self.tasks(mappedTasks);
    });    
}

ko.applyBindings(new TaskListViewModel());
Stokedout
  • 11,003
  • 5
  • 24
  • 30
  • Thanks, but that is not what I'm looking for; I need to detect the change of single values - not arrays. – larsw Jan 04 '13 at 12:16
  • Looking at your question again, what's your reason for keeping them in a separate variable? Is this to determine whether the user has changed anything on that page alone? Some kind of iteration will be involved if you do or don't use a mapper – Stokedout Jan 04 '13 at 12:44
  • Yes, I want to a) only submit back changed values, but also b) pair the new and the old value so that I can do optimistic concurrency checking on the server-side. – larsw Jan 04 '13 at 13:53
  • 1
    I've had a ponder and I'd probably add an extra normal variable for each property to hold the original value. After this create a computed variable that will only return the properties which have changed with their old properties side by side. Does this make sense? You can use that computed variable when you postback to the server. – Stokedout Jan 04 '13 at 14:56