2013-05-02 15 views
5

Ho bisogno di modificare un array di numeri interi in un'applicazione web, utilizzando Javascript e Knockout.js. Questo array sarà associato a caselle di testo e ogni volta che viene modificato il valore di una casella di testo, la matrice viene aggiornata. E quando viene aggiornato, viene calcolata la somma degli elementi.Variabili di tracciamento - elemento osservabile in osservabileArray

Questo è il mio primo tentativo: http://jsfiddle.net/ZLs2A/0/. Non funziona (il valore della somma non viene aggiornato quando si digita un nuovo valore per qualsiasi elemento). In quel momento ho capito che observableArray attiva la funzione somma solo dopo aver inserito o rimosso elementi.

<h4>Numbers</h4> 
<button data-bind="click: add">Add</button> 
<ul data-bind="foreach: numbers"> 
    <li> 
     <input data-bind="value: $data"></input> 
    </li> 
</ul> 
<span data-bind="text: sum"></span> 

function MyViewModel() { 
    var self = this; 

    self.numbers = ko.observableArray([ 
     1, 
     2, 
     3 
    ]); 

    self.sum = ko.computed(function() { 
     var items = self.numbers(); 
     var total = 0; 
     for (var i = 0; i < items.length; i++) { 
      total += parseInt(items[i]); 
     } 
     return total; 
    }); 

    self.add = function() { 
     var lastIndex = self.numbers().length - 1; 
     var lastValue = self.numbers()[lastIndex]; 
     self.numbers.push(lastValue + 1); 
    } 
} 

ko.applyBindings(new MyViewModel()); 

Il mio prossimo tentativo è stato quello di rendere ogni elemento della matrice numeri un'osservabile (http://jsfiddle.net/ZLs2A/1/). Non ha funzionato di nuovo.

self.numbers = ko.observableArray([ 
    ko.observable(1), 
    ko.observable(2), 
    ko.observable(3) 
]); 

Il mio ultimo tentativo è stato la creazione di una nuova classe (ArrayItem) per contenere il valore dell'elemento all'interno di una proprietà osservabile. Questa volta ha funzionato! (http://jsfiddle.net/ZLs2A/3/)

<h4>Numbers</h4> 
<button data-bind="click: add">Add</button> 
<ul data-bind="foreach: numbers"> 
    <li> 
     <input data-bind="value: value"></input> 
    </li> 
</ul> 
<span data-bind="text: sum"></span> 

function MyViewModel() { 
    var self = this; 

    self.numbers = ko.observableArray([ 
     new ArrayItem(1), 
     new ArrayItem(2), 
     new ArrayItem(3) 
    ]); 

    self.sum = ko.computed(function() { 
     var items = self.numbers(); 
     var total = 0; 
     for (var i = 0; i < items.length; i++) { 
      total += parseInt(items[i].value()); 
     } 
     return total; 
    }); 

    self.add = function() { 
     var lastIndex = self.numbers().length - 1; 
     var lastItem = self.numbers()[lastIndex]; 
     var newValue = parseInt(lastItem.value()) + 1; 
     self.numbers.push(new ArrayItem(newValue)); 
    } 
} 

function ArrayItem(value){ 
    var self = this; 
    self.value = ko.observable(value); 
} 

ko.applyBindings(new MyViewModel()); 

Tuttavia, non mi piace avere per creare questa nuova classe di ArrayItem. C'è un modo per sbarazzarsene, facendo in modo che l'esempio funzioni solo con un array osservabile di elementi osservabili (come il mio secondo tentativo)?

+2

L'autore del KO risposto [questo (? Possibile duplicare) domanda] (http://stackoverflow.com/questions/9510539/knockout-js-how-to-correctly-bind-an -observablearray), fondamentalmente in un modo simile alla versione finale con un costruttore 'ArrayItem' (ha solo in linea quella funzione). La risposta è di un anno, quindi qualcosa potrebbe essere cambiato nel frattempo ... Se non lo fosse, sembrerebbe che tu abbia già risposto alla tua stessa domanda. – Jeroen

+0

Probabilmente vale la pena citare l'integrazione di Breeze.js con Knockout.js che aggiunge Change Tracking tra le altre cose. http://www.breezejs.com/ –

risposta

2

Knockout non traccia il valore, ma come soluzione alternativa è possibile utilizzare la pressione di un tasto evento oppure modificare e aggiornare i valori manualmente. Vedere violino: http://jsfiddle.net/tkirda/ZLs2A/4/

function MyViewModel() { 
    var self = this; 

    self.numbers = ko.observableArray([ 
     1, 
     2, 
     3 
    ]); 

    self.onChange = function(val, e){ 
     var el = e.srcElement; 
     var newVal = parseInt(el.value); 
     var index = parseInt(el.getAttribute('data-index')); 
     self.numbers()[index] = newVal; 
     self.updateSum(); 
    } 

    self.sum = ko.observable(0); 

    self.updateSum = function() { 
     var items = self.numbers(); 
     var total = 0; 
     for (var i = 0; i < items.length; i++) { 
      total += parseInt(items[i]); 
     } 
     self.sum(total); 
    }; 

    self.updateSum(); 

    self.add = function() { 
     var lastIndex = self.numbers().length - 1; 
     var lastValue = self.numbers()[lastIndex]; 
     self.numbers.push(lastValue + 1); 
    } 
} 

ko.applyBindings(new MyViewModel()); 
+0

Anche se sembra funzionare con IE11, la somma nell'esempio jsfiddle non si aggiorna sulle modifiche dei valori nel campo di testo in Firefox 45.0.1 – Stefan

Problemi correlati