Question

I am complete novice to knockout and facing following problem.

Following are my knockout objects

    var modelEmployee = {
    EmpRec: null
    };

    var viewModel = {
    lookupCollection:  ko.observableArray(),
    selectedItem: ko.observable(),
    EditedItem: ko.observable()
    };

following method is called on click of edit link. I am copying the current row of an array to EditedItem and also to object modelEmployee.

    viewModel.EditItem = function (item) {
    viewModel.EditedItem(item);
    modelEmployee.EmpRec = viewModel.EditedItem;
    }

If user cancels the edit then I want to copy row from modelEmployee back to my array

    viewModel.Cancel = function () {
    viewModel.EditedItem = modelEmployee.EmpRec;
    }

Whenever user changes the value in input control values in all the objects are updated. modelEmployee is not set as an observable but still it is being updated.

I checked many forums but could not find the satisfactory answer.

Was it helpful?

Solution

So let's say, for arguments sake, you have an employee record object that you want to copy that looks something like this:

function EmployeeRecord(firstName, lastName, emplNumber) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.number = emplNumber;
    this.someNestedObject = {
        foo: bar
    };
}

To make a deep copy, you would need to create a new object and copy each field. If a field is itself an object, you would need to create another new object inside your copy and copy each field from that object too. Something like:

 var myCopy = new EmployeeRecord(source.firstName, source.lastName, source.number);
 myCopy.someNestedObject = {
     foo: source.foo
 };

This can get a little tedious for large objects with lots of fields, so a slightly lazy way to do this is to (ab)use JSON.stringify and JSON.parse to serialize and deserialize your object to a string and back again:

var myCopy = JSON.parse(JSON.stringify(source));

So in your case - if you only need to keep the object as a backup to restore later, you could do this:

viewModel.EditItem = function (item) {
    viewModel.EditedItem(item);
    modelEmployee.EmpRec = JSON.stringify(viewModel.EditedItem());     // note: if you really need EmpRec to be an object, just JSON.parse it back again
}

And then when you restore it:

viewModel.Cancel = function () {
    viewModel.EditedItem(JSON.parse(modelEmployee.EmpRec));     // note: don't parse here if you parsed it when you saved it.
}

Also note that the JSON trick will not copy functions. So if you have functions in your object you will need to copy them manually (if you need them). This is an important caveat with Knockout because observables are actually functions, so if you object had observables, the serialize/deserialize trick might not work for you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top