нокаут.Computed() не обновляется с помощью observableArray
у меня есть следующий код:
// First we define our gift class, which has 2 properties:
// a Title and a Price.
// We use knockout js validation to ensure that the values input are suitable/
function Gift(item)
{
var self = this;
self.Title = ko.observable(item.Title);
// attach some validation to the Title property courtesy of knockout js validation
self.Title.extend({
required: true,
minLength: 3,
pattern: {
message: 'At least ',
params: '^[a-zA-Z]+s?[a-zA-Z]*'
}
});
self.Price = ko.observable(item.Price);
self.Price.extend({required:true,number:true,min:0.1,max:1000});
};
var viewModelForTemplated =
{
gifts: ko.observableArray(), // gifts will be an array of Gift classes
addGift: function ()
{
this.gifts.push(new Gift({ Title: "", Price: "" }));
},
removeGift: function (gift)
{
this.gifts.remove(gift);
},
totalCost: ko.computed(function () {
if (typeof gifts == 'undefined')
return 0;
var total = 0;
for (var i = 0; i < gifts().length; i++)
{
total += parseFloat(gifts()[i].Price());
};
return total;
})
}
$(document).ready(function ()
{
// load in the data from our MVC controller
$.getJSON("gift/getdata", function (allGifts)
{
var mappedgifts = $.map(allGifts, function (gift)
{
return new Gift(gift);
});
viewModelForTemplated.gifts(mappedgifts);
});
ko.applyBindings(viewModelForTemplated, $('#templated')[0]);
}
и затем (над скриптом)
<div id="templated">
<table >
<tbody data-bind="template: { name: 'giftRowTemplate', foreach: gifts }"></tbody>
</table>
<script type="text/html" id="giftRowTemplate">
<tr>
<td>Gift name: <input data-bind="value: Title"/></td>
<td>Price: $ <input data-bind="value: Price"/></td>
<td><a href="#" data-bind="click: function() { viewModelForTemplated.removeGift($data) }">Delete</a></td>
</tr>
</script>
<p>Total Cost <span data-bind="text: totalCost"></span> </p>
<button data-bind="click: addGift">Add Gift</button>
<button data-bind="click: save">Save</button>
</div>
метод totalCost запускается только один раз, когда массив подарков пуст, и я могу нажать или удалить элементы на observableArray() нет проблем, но ничего не срабатывает .
Как получить диапазон, относящийся к totalCost для обновления? Бьюсь об заклад, это что-то простое:)
Спасибо за вашу помощь.
2 ответов
вам нужно развернуть ваш наблюдаемых:
totalCost: ko.computed(function () {
//also, you forgot typeof below
if (typeof gifts == 'undefined')
return 0;
var total = 0; //here \/
for (var i=0; i < gifts().length; i++)
{ //and here \/
total += parseFloat(gifts()[i].Price());
};
return total;
})
почему это не обновление, потому что
gifts.length
всегда оценивает 0
, и никогда не входя в цикл. И даже если это так,
gifts[i].Price()
не будет работать по той же причине; вам нужно развернуть наблюдаема.
обратите внимание, что причина, по которой длина оценивается до нуля, когда вы не разворачиваете его, потому что вы получаете длина фактического наблюдаемого массив функции. Все наблюдаемые в Knockout реализуются как обычные функции; когда вы не разворачиваете его, вы ударяете саму функцию, а не базовый массив.
редактировать
кроме того, вам нужно ссылаться на подарки с this.gifts
, поскольку это свойство объекта. Вот почему это не сработало; подарки-это всегда не определено.
тем не менее, вам также нужно сделать еще немного работы, чтобы получить ko computeds для работы с объектным литералом. Читайте здесь для получения дополнительной информации:
http://dpruna.blogspot.com/2013/09/how-to-use-kocomputed-in-javascript.html
вот как я бы сделал вашу модель просмотра:
function Vm{
this.gifts = ko.observableArray(); // gifts will be an array of Gift classes
this.addGift = function () {
this.gifts.push(new Gift({ Title: "", Price: "" }));
};
this.removeGift = function (gift)
{
this.gifts.remove(gift);
};
this.totalCost = ko.computed(function () {
var total = 0;
for (var i = 0; i < this.gifts().length; i++)
{
total += parseFloat(this.gifts()[i].Price());
};
return total;
}, this);
}
var viewModelForTemplated = new Vm();
вы должны развернуть observableArray
С помощью ()
при применении индексатора к нему. Update totalCost
следующим образом:
totalCost: ko.computed(function () {
if (this.gifts == 'undefined')
return 0;
var total = 0;
for (var i=0; i<this.gifts().length;i++)
{
total += parseFloat(this.gifts()[i].Price());
};
return total;
})