2012-11-05 8 views
22

Fondamentalmente ho un array osservabile ei valori per ogni elemento non sono osservabili. Ciò significa che quando cambio un valore di un elemento, l'interfaccia utente all'interno di un ciclo foreach del observableArray non si aggiorna di conseguenza.Aggiorna osservableArray quando gli articoli non sono osservabili

Significa un enorme cambiamento se devo impostarli su osservabile, quindi c'è un modo per aggiornare manualmente l'interfaccia utente o l'ObservableArray?

risposta

46

Sì, è possibile chiamare valueHasMutated funzione per l'array:

yourArray.valueHasMutated(); 

EDIT: violino

self.refresh = function(){ 
    var data = self.array().slice(0); 
    self.array([]); 
    self.array(data); 
}; 

Qui sta lavorando: se prima non ha aiutato si può fare 'sporca' di aggiornamento : http://jsfiddle.net/vyshniakov/FuEy6/2/

+5

Questo ancora non aggiorna l'interfaccia utente per me – user1166905

+1

valoreHasMutated ha funzionato bene per me. – Edyn

+7

perché è necessario creare una copia dell'array chiamando slice (0)? anche il seguente funziona e ancora meglio 'var data = self.array(); self.array (null); self.array (data);' –

5

Ho finito per usare l'approccio sporco dall'alto ma fatto in modo che tutti i miei array osservabili avessero questa funzionalità.

ko.observableArray.fn.refresh = function() { 
     var data = this().slice(0); 
     this([]); 
     this(data); 
    }; 

Il valore HasMutated non ha funzionato per me. Il suo tipo di zoppo, l'intera lista deve essere aggiornata. O nel mio caso trovare un modo per estendere il plugin di mappatura ko per riempire gli array osservabili con oggetti osservabili.

+2

'var data = this()/*. Slice() * /; this (null); this (data);' funzionerà altrettanto bene e ancora più veloce –

16

Quando si dispone di un array osservabile con elementi non osservabili e alcune proprietà di uno degli elementi nell'array cambia , se si desidera aggiornare solo elemento, è possibile utilizzare indexOf e splice, in questo modo:

var changedIdx = obsArray.indexOf(changedItem); 
obsArray.splice(changedIdx , 1); // removes the item from the array 
obsArray.splice(changedIdx , 0, changedItem); // adds it back 

quello che fa, è alla ricerca per l'elemento della matrice, rimuoverlo, e inserendolo di nuovo. Quando viene inserito di nuovo, l'elemento viene associato di nuovo, con i nuovi valori.

Se ti piace questa soluzione, è possibile estendere la funzionalità di tutte le matrici osservabili ko, in questo modo:

ko.observableArray.fn.refresh = function (item) { 
    var index = this['indexOf'](item); 
    if (index >= 0) { 
     this.splice(index, 1); 
     this.splice(index, 0, item); 
    } 
} 

Poi, quando si modifica un elemento di un array, è sufficiente per effettuare la chiamata:

obsArray.refresh(changedItem); 

Se si dispone di molti elementi in vostro allineamento si otterrà una migliore performace rispetto alla dirty aggiornamento di Artem Vyshniakov, che aggiorna le associazioni per tutti gli elementi della matrice, e non solo per la cambiata di una .

Nota: il valueHasMutated, appart venga documentato (e per uso interno, immagino), controlla solo se la matrice stessa è cambiata, non se gli elementi non osservabili nella matrice sono cambiati, così doesn' lavoro. Cioè rileva solo se sono stati aggiunti elementi alla matrice, elementi rimossi dall'array, elementi modificati della matrice con nuovi elementi diversi o modificato l'ordine degli elementi. Ma non controlla se gli elementi stessi sono stati modificati

+0

bellissime cose utili grazie – Andrew

+0

Nota che 'obsArray.indexOf() 'cerca l'elemento semplicemente abbinandolo al valore usando' === 'ma in javascript' {'x': 'X'} === {'x': 'X'} 'return false –

+0

Hai ragione. Tuttavia, in questo scenario ** hai un riferimento all'elemento dell'array che vuoi mofidy **. Non stai modificando un oggetto che assomiglia a quello nell'array, ma l'oggetto nell'array. Quindi, usando 'indexOf' lo troverà. Se hai cambiato un oggetto che non è nell'array, dovresti sostituire l'oggetto nell'array con quello nuovo, che è diverso dal cambiare le proprietà di ** un elemento nell'array ** e notificare che è cambiato, L'altro caso è completamente diverso. – JotaBe

0

Ho trovato una soluzione semplice sostituendo l'intero oggetto nell'array.

In questo esempio parametro ix è l'indice, Oline è l'oggetto aggiornato e oVM.objProps.le righe contengono l'array. La soluzione ha funzionato come un campione.

/* This contortion causes the computed function to fire because 
* we have replaced the entire line object. 
*/ 
function forceRefresh(ix,oLine) { 
    var oVM = pme.getVM(); 
    oLine = JSON.parse(JSON.stringify(oLine)); 
    oVM.oObjProp.lines[ix] = oLine; 
} 
Problemi correlati