Potrzebuję edytować tablicę liczb całkowitych w aplikacji internetowej, używając Javascript i Knockout.js. Tablica ta będzie powiązana z polami tekstowymi, a ilekroć zmieni się wartość dowolnego pola tekstowego, tablica zostanie zaktualizowana. A gdy zostanie zaktualizowany, obliczana jest suma elementów. To jest moja pierwsza próba: http://jsfiddle.net/ZLs2A/0/. Nie działa (wartość sumy nie jest aktualizowana podczas wpisywania nowej wartości dla dowolnego elementu). Wtedy uświadomiłem sobie, że obserservableArray wywoła funkcję sumującą dopiero po wstawieniu lub usunięciu elementów.Zmiany śledzenia - obserwowalny element w obserservArray
<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());
Moja następna próba była, aby każdy element tablicy liczb zauważalny (http://jsfiddle.net/ZLs2A/1/). To już nie działało.
self.numbers = ko.observableArray([
ko.observable(1),
ko.observable(2),
ko.observable(3)
]);
Moja ostatnia próba polegała na utworzeniu nowej klasy (ArrayItem) w celu zachowania wartości elementu wewnątrz obserwowalnej właściwości. Tym razem zadziałało! (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());
Jednak nie lubią mieć do stworzenia tej nowej klasy ArrayItem. Czy istnieje sposób, aby się go pozbyć, dzięki czemu przykład działa tylko o obserwowalne Array z obserwowalnych elementów (jak moja druga próba)?
Autor KO odpowiedział [ten (? Możliwy duplikat) Pytanie] (http://stackoverflow.com/questions/9510539/knockout-js-how-to-correctly-bind-an -observablearray), w zasadzie w podobny sposób do twojej ostatecznej wersji z konstruktorem 'ArrayItem' (po prostu wstawia tę funkcję). Odpowiedź jest roczna, więc coś mogło się zmienić w międzyczasie ... Jeśli tak się nie stało, wydaje się, że już odpowiedziałeś na własne pytanie. – Jeroen
Warto wspomnieć o integracji Breeze.js z Knockout.js, która dodaje między innymi śledzenie zmian. http://www.breezejs.com/ –