Part of my HTML code:
<!-- ko foreach: teamMembers -->
<tr>
<!-- ko foreach: days -->
<td>
<!-- ko foreach: $data -->
<input type="text" data-bind="value: number1">
<input type="text" data-bind="value: number2">
<!-- /ko -->
</td>
<!-- /ko -->
<td>Total sum</td>
<td>
<button class="btn" data-bind='click: $root.addShift'>
Add shift
</button>
</td>
</tr>
<!-- /ko -->
The viewmodel code:
function TimeCardViewModel() {
var self = this;
self.teamMembers=ko.observableArray();
self.addShift = ko.pureComputed(function() { });
}
$.ajax({
type:"POST"
url: "/...json"
}).then(function(data){
for (var i=0; i<data.length; i++) {
timeCardViewModel.teamMembers.push({days:data[i]});
}
},
function(){
console.log('failure');
}
)
days is an array of arrays
; each of the latter ones include one or more objects.Therefore, in the template, $data represents an array of objects which lie inside the days array! Each object has a number1 property and a number2 property.
I want to calculate the sum of the values of these two numbers for all the objects inside days which is an array of arrays and there are lots of them inside teamMembers which also is an array of arrays. So, I want this to be done for every element-array of teamMembers . How may I achieve that? I want addShift function to do that and get the sum inside <td>Total sum</td>
which exists for every element of teamMembers .Sorry if not describing well the whole issue...
If you're working with these kinds of nested data, you might want to create viewmodels for each of your elements.
If I get your structure correctly there's:
If you define specific objects for each of these elements you get a good overview of the logic behind your computed values.
For example:
totalHours
of a shift, is number1 + number2
totalHours
of a day, is the totalHours
of each shift summed Two things you'll benefit from using:
ko.pureComputed
to automatically recalculate total hours Array.prototype.reduce
to sum up all values in an array I'd suggest taking a look at the example below to get a feel for how you could structure the elements that make up your TimeCard
. You might not need this many class levels, but it makes it easier to follow.
Note that I didn't put in any code to convert your JSON data to new viewmodel instances. If you need help with that, let me know in the comments.
function Shift(hoursA, hoursB) { var self = this; this.hoursA = ko.observable(hoursA); this.hoursB = ko.observable(hoursB); // Computed 1: Adds `number1` to `number2` when one of them // changes this.totalHours = ko.pureComputed(function() { return self.hoursA() + self.hoursB(); }); }; function Day(initialShifts) { var self = this; this.shifts = ko.observableArray(initialShifts); // Computed 2: Adds the `totalHours` for each shift this.totalHours = ko.pureComputed(function() { return self.shifts().reduce(function(result, shift) { return result + shift.totalHours(); }, 0); }); }; function TeamMemberViewModel(initialDays) { var self = this; this.days = ko.observableArray(initialDays); // Computed 3: Adds the `totalHours` for each day this.totalHours = ko.pureComputed(function() { return self.days().reduce(function(result, day) { return result + day.totalHours(); }, 0); }); }; function TimeCardViewModel() { var self = this; this.teamMembers = ko.observableArray(); // Computed 4: Adds the `totalHours` for each member this.totalHours = ko.pureComputed(function() { return self.teamMembers().reduce(function(result, member) { return result + member.totalHours(); }, 0); }); };
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.