2016-05-09 17 views
6

Ho un oggetto selectedItem in Angolare, contiene altri oggetti e matrici. Creo una copia profonda utilizzando un trucco JSON:Come attraversare l'oggetto JS e tutti gli array e gli oggetti all'interno per confrontarlo con la sua copia?

$scope.editableItem = JSON.parse(JSON.stringify($scope.selectedItem)) 

allora io uso editableItem modello input, modificare alcuni valori all'interno. selectedItem non cambia. Quindi voglio inviare tramite PATCH tutte le modifiche apportate, ma non i campi che non sono stati modificati. Quindi ho bisogno di togliere lo editableItem da tutti i campi uguali nello selectedItem invariato.

Come farlo in modo efficiente? Stavo pensando di attraversare l'oggetto ricorsivamente usando Underscore, ma mi piacerebbe davvero sapere se è un buon modo di pensare prima di affrontarlo.

In alternativa, potrei probabilmente creare un terzo oggetto che contenga solo campi toccati dal secondo, aggiunti dinamicamente, ma non sono sicuro di come affrontarlo.

MODIFICATO: Per essere chiari, mi aspetto che la risposta sia generica e presupponga la struttura di oggetti più complicata possibile. Ad esempio, nessuna risposta da this question è applicabile in quanto entrambi presuppongono che l'oggetto abbia solo campi semplici o che debbano avere un osservatore angolare impostato esplicitamente per ogni campo separatamente.

+0

Come si desidera esprimere le differenze negli array? Come array sparsi (che non puoi convertire correttamente in JSON)? – CherryDT

+0

Buon punto. Immagino: se non c'è differenza, allora non mandare affatto l'array. Se c'è una differenza, invia l'intero array modificato. Quindi l'array nel suo insieme è un valore che può essere cambiato e passato o invariato e non passato. – Senthe

risposta

0

Questo è quello che ho finito. Forse aiuterà qualcuno. Ho usato la libreria DeepDiff. Il codice è in CoffeScript, dovrebbe essere facile da tradurre in JavaScript se ne ha bisogno.

$scope.getChangesObject =() -> 
     selected = $scope.selectedItem 
     editable = $scope.editableItem 
     changes = {} 
     differences = DeepDiff(selected, editable) 

     for diff in differences 
     formattedPath = "" 
     for pathPart, index in diff.path 
      if index isnt diff.path.length - 1 
      formattedPath += pathPart + "." 
      else 
      formattedPath += pathPart 
     changes[formattedPath] = editable[formattedPath] 

     changes 
1

faccio qualcosa di simile con una funzione come questa:

function getUpdateObject(orig, current) { 
    varChanges = {}; 

    for (var prop in orig) { 
     if (prop.indexOf("$") != 0 && orig[prop] !== current[prop]) { 
      varChanges[prop] = current[prop]; 
     } 
    } 
    return varChanges ; 
}; 

Io non credo che questo ti porterà per tutto il tragitto. Non lo sto usando in nessuno scenario in cui gli oggetti hanno oggetti membro o matrici, ma dovresti essere in grado di verificare se "prop" è un oggetto o array e chiamarlo ricorsivamente. Il più grande avvertimento che vedo per questo approccio è che se si dispone di una struttura profonda e annidata, è possibile che non si rilevino cambiamenti finché non si scende di diversi livelli. Probabilmente dovresti mantenere tutta la gerarchia potenziale per una proprietà modificata in memoria, quindi quando rilevi una modifica a un livello inferiore, scrivi l'intera gerarchia sull'oggetto di output.

+0

Posso creare una copia di un terzo oggetto e quindi cancellare i campi che sono uguali da esso, probabilmente sarebbe più facile che crearlo al volo. – Senthe

+0

Suoni ragionevoli. Tuttavia, richiede più memoria. –

+0

Che cosa fa 'property.indexOf (" $ ")'? – Senthe

Problemi correlati