2012-05-10 3 views
11

Quelle est la meilleure façon de cloner des objets observables dans Knockout pour faire le type de mécanisme de transactions?

Par exemple l'édition de ce modèle:
Meilleure façon de cloner les observables?

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

Je veux enregistrer l'état de cet objet avant utilisateur modifier. Et si l'utilisateur va annuler l'édition - l'état de l'objet de restauration.

simple est de créer juste un autre projet comme:

self.tempAction = new Action(action.name(), action.ownerType(), action.condition(), action.expression(), action.args()); 

Mais je ne suis pas sûr que c'est une solution élégante ..

, quelles idées?

Répondre

15

-je faire quelque chose comme ce qui suit:

D'abord, j'ai une fonction qui imite la fonction de jQuery $.extend. Il remplit un objet target avec toutes les valeurs de propriété observable (ou non observables) de l'objet source.

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

, j'ai une fonction copy qui convertit essentiellement l'objet à copier dans JSON et prend alors la copie JSON et construit un nouvel objet javascript. Cela garantit que tous les pointeurs de mémoire ne sont pas copiés et que vous avez un nouvel objet qui correspond à votre original. L'une clé ici est que vous ne devez passer dans une instance vide d'un nouvel objet (sinon nous aurions aucune idée de ce que les propriétés à remplir)

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

Vous pouvez alors l'utiliser comme ceci:

var tempAction = ko.utils.clone(action, new Action()); 
+0

Pourriez-vous utiliser simplement le plugin ko.mapping pour mapper de l'objet source original au nouvel objet cible? – jaffa

+0

@jaffa - oui, le plugin de cartographie serait une option appropriée. Cependant, il peut être exagéré pour des besoins triviaux. En outre, j'ai trouvé la fonction 'extendObservable' assez utile dans les situations où le plugin de mapping n'était pas nécessaire à l'application. – ericb

+0

Comment cela fonctionne avec les valeurs ko.computed? Je pense qu'utiliser toJSON et JSON.parse pour copier un objet perdra toutes ses valeurs calculées. –

Questions connexes