2013-02-19 1 views
10

Ho seguito array JavaScript,Come aggiornare l'elemento array osservabile in knockoutjs?

[{"unitPrice": 2499,"currency":"$","productId":1,"retailerId":1,"productName":"XX ","formattedPrice":"$ 2,499","productImage":"Images/2012_08_12_00_45_39_4539.jpg","productQuantity":"9","totalPrice":19992}, 
{"unitPrice": 4999,"currency":"$","productId":2,"retailerId":1,"productName":"XX","formattedPrice":"$ 4,999","productImage":"Images/2012_08_12_00_46_45_4645.jpg","productQuantity":2,"totalPrice":9998}, 
{"unitPrice":4555,"currency":"$","productId":1,"retailerId":1,"productName":"XXXXX","formattedPrice":"$ 4,555","productImage":"Images/2013_02_12_10_57_49_5749_9868.png","productQuantity":3,"totalPrice":13665}] 

Ecco l'html relevent,

<table> 
<tbody data-bind="foreach: $root"> 
        <tr> 
         <td><img width="45" height="45" alt="" data-bind="attr:{src: productImage}"/></td> 
         <td><span data-bind="html: productName"></span></td> 
         <td><span data-bind="html: formattedPrice"></span></td> 
         <td><input type="number" class="quantity" data-bind="value: productQuantity, attr:{'data-id': productId }" /></td> 
         <td><span data-bind="html: totalPrice"></span></td> 
        </tr> 
       </tbody> 
</table> 

Poi ho creato matrice osservabile come,

observableItems = ko.observableArray(items); 
ko.applyBindings(observableItems); 

Ora sono stato in grado di ottenere un elemento specfico utilizzando,

 var obj = ko.utils.arrayFirst(list(), function (item) { 
      return item.productId === id; 
     }); 

Tuttavia quando cambio,

item.productQuantity = 20; 

Ma interfaccia utente non sta aggiornando. Anche provato,

item.productQuantity(item.productQuantity) 

Ma ottenere errore productQuantity non è una funzione

risposta

17

Il comportamento precedente è perché solo l'array è osservabile e non i singoli elementi all'interno dell'array o le proprietà di ogni elemento.

Quando si esegue item.productQuantity = 20;, questo aggiornerà la proprietà ma poiché non è osservabile, l'interfaccia utente non viene aggiornata.

Similario, item.productQuantity(20) ti dà un errore perché productQuantity non è un osservabile.

Si dovrebbe cercare di definire la struttura dell'oggetto per ogni elemento dell'array e quindi aggiungere elementi di quel tipo al proprio array osservabile. Una volta fatto, sarai in grado di fare qualcosa come item.productQuantity(20) e l'interfaccia utente si aggiornerà immediatamente.

EDIT Aggiunta la funzione fornita dall'OP :). Questa funzione convertirà ogni proprietà degli elementi di un array in osservabili.

function convertToObservable(list) 
{ 
    var newList = []; 
    $.each(list, function (i, obj) { 
     var newObj = {}; 
     Object.keys(obj).forEach(function (key) { 
      newObj[key] = ko.observable(obj[key]); 
     }); 
     newList.push(newObj); 
    }); 
    return newList; 
} 

FINE EDIT

Se non si riesce a cambiare quel pezzo di codice, si può anche fare qualcosa di simile observableItems.valueHasMutated(). Tuttavia, questa non è una buona cosa da fare in quanto segnala a KO e alla tua interfaccia utente che l'intero array è cambiato e l'interfaccia utente renderà l'intero array basato sui binding.

+0

osservableItems.valueHasMutated() non funziona – user960567

+0

Ottenuto aggiungendo questa funzione, conve function rtToObservable (list) { var newList = []; $.each (list, function (i, obj) { var newObj = {}; Object.keys (obj) .forEach (funzione (chiave) { newObj [chiave] = ko.observable (obj [chiave]); }); newList.push (newObj); }); return newList; } – user960567

+0

Si prega di inserire questa risposta interna. – user960567

9

Si può facilmente utilizzare ko.mapping plugin per convertire oggetto per diventare osservabile: http://knockoutjs.com/documentation/plugins-mapping.html

Convertire regolare entità JS per entità osservabile:

var viewModel = ko.mapping.fromJS(data); 

Converti oggetto osservabile al normale oggetto JS:

var unmapped = ko.mapping.toJS(viewModel); 
+0

ok, ma se l'array osservabile è un array di molti oggetti, come aggiorneresti una singola proprietà di un oggetto nell'array usando questo metodo? – Andrew

+0

Hai bisogno di sapere esattamente quale oggetto sarà aggiornato nell'array, quindi converti quel particolare oggetto in osservabile, anche per quanto riguarda le prestazioni. –