koo-mappable array
by mckennatim
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.3.5/knockout.mapping.js"></script>
<table id="myTable" class="tablesorter">
<thead>
<tr>
<th>Mon 1 </th>
<th>Mon 2 </th>
<th>Mon 3 </th>
<th>Total </th>
</tr>
</thead>
<tbody data-bind='foreach:List'>
<tr>
<!-- ko foreach:Entries-->
<td>
<input size="3" type="text" data-bind="value:Hours, valueUpdate:'afterkeydown'"/>
</td>
<!-- /ko -->
<td>
<span data-bind="text:Total"></span>
</td>
</tr>
</tbody>
</table>
JavaScript
function ViewModel() {
var self = this
self.List = ko.observableArray([])
self.LoadData = function () {
var data = {
"Lines": [
{"Entries": [{"Hours": 5.5},{"Hours": 2.50},{"Hours": 3.75}]},
{"Entries": [{"Hours": 5.1},{"Hours": 2.00},{"Hours": 4.75}]},
{"Entries": [{"Hours": 1.2},{"Hours": 3.00},{"Hours": 2.12}]
}]
}
self.List(ko.mapping.fromJS(data.Lines)())
////this makes every child observable
}
self.applyTotals = function(){
ko.utils.arrayForEach(self.List(), function(vm){
vm.Total = ko.computed(function(){
var s = 0;
ko.utils.arrayForEach(this.Entries(), function(entry){
var p = parseFloat(entry.Hours(), 10);
if (!isNaN(p)) {
s += p;
}
});
return s;
}, vm);
});
}
self.LoadData();
console.log(self.List());
self.applyTotals();
}
ko.applyBindings(new ViewModel())