What is the best way to clone Observable objects in Knockout to make kind of transactions mechanism?
For example editing this model:
var Action = function (name, ownerType, condition, expression, args) {
var self = this;
this.name = ko.observable(name);
this.ownerType = ko.observable(ownerType);
this.condition = ko.observable(condition);
this.expression = ko.observable(expression);
this.args = ko.observable(args);
};
I want to save state of that object before user will edit it. And if user will cancel editing - rollback object state.
Simplest way is just create another project like:
self.tempAction = new Action(action.name(), action.ownerType(), action.condition(), action.expression(), action.args());
But I'm not sure that it is elegant solution..
So, any ideas?
I usually do something like the following:
First I have a function that mimics jQuery's $.extend
function. It populates a target
object with all of the observable
(or non-observable) property values of the source
object.
// extends observable objects intelligently
ko.utils.extendObservable = function ( target, source ) {
var prop, srcVal, isObservable = false;
for ( prop in source ) {
if ( !source.hasOwnProperty( prop ) ) {
continue;
}
if ( ko.isWriteableObservable( source[prop] ) ) {
isObservable = true;
srcVal = source[prop]();
} else if ( typeof ( source[prop] ) !== 'function' ) {
srcVal = source[prop];
}
if ( ko.isWriteableObservable( target[prop] ) ) {
target[prop]( srcVal );
} else if ( target[prop] === null || target[prop] === undefined ) {
target[prop] = isObservable ? ko.observable( srcVal ) : srcVal;
} else if ( typeof ( target[prop] ) !== 'function' ) {
target[prop] = srcVal;
}
isObservable = false;
}
return target;
};
Then I have a copy
function that essentially converts the object to be copied into JSON
and then takes the JSON
copy and builds a new javascript object. This ensures all the memory pointers are not copied and you have a brand new object that matches your original one. The one key here is that you do have to pass in an empty instance of a new object (otherwise we would have no idea what properties to populate)
// then finally the clone function
ko.utils.clone = function(obj, emptyObj){
var json = ko.toJSON(obj);
var js = JSON.parse(json);
return ko.utils.extendObservable(emptyObj, js);
};
You can then use it like so:
var tempAction = ko.utils.clone(action, new Action());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With