Knockout.js:对 table 和 foreach 中的分组值求和
Knockout.js: Sum grouped values within table and foreach
具有数据绑定的 table 当前如下所示:
Source Calls ChargeableCalls
Car Insurance
08434599111 3 2
08934345122 2 1
Home Insurance
08734599333 3 2
08034345555 2 1
所需的输出 应该像下面的例子,table 应该包含 Calls
和 ChargeableCalls
的总值分组table.
中所有 Calls
和 ChargeableCalls
的除法和总值
Source Calls ChargeableCalls
Car Insurance
08434599154 3 2
08934345555 2 1
Total Calls 5 Total CC 3
Home Insurance
08434599154 6 3
08934345555 1 0
Total Calls 7 Total CC 3
Total Calls All 24 Total CC All 12
以下是 table 中的绑定:
<table class="table table-condensed" id="reportData">
<thead>
<tr>
<th>Source</th>
<th>TotalCalls</th>
<th>ChargeableCalls</th>
</tr>
</thead>
<tbody data-bind="foreach: groups">
<!-- ko foreach: $root.getGroup($data) -->
<tr data-bind="if: $index() == 0">
<td colspan="3" data-bind="text: division" class="division"></td>
</tr>
<tr>
<td data-bind="text: source"></td>
<td data-bind="text: totalCalls"></td>
<td data-bind="text: chargeableCalls"></td>
</tr>
<!-- /ko -->
</tbody>
这是我的视图模型:
function GroupedReportingViewModel() {
var self = this;
self.results = ko.observableArray();
self.groupedResults = {};
self.getGroup = function (group) {
return self.groupedResults[group];
};
self.groupedResultsC = ko.computed(function () {
self.groupedResults = {};
ko.utils.arrayForEach(self.results(), function (r) {
if (!self.groupedResults[r.division]) self.groupedResults[r.division] = [];
self.groupedResults[r.division].push(r);
});
return self.groupedResults;
});
self.groups = ko.computed(function () {
var g = [];
for (x in self.groupedResultsC())
g.push(x);
return g;_
});
}
var model = new GroupedReportingViewModel();
ko.applyBindings(model);
results
observableArray 从 ajax 响应中填充,如下所示:
success: function (jsondata) {
model.results(jsondata["Data"]["Report"]);
}
jsondata
对象如下所示:
{"Data":
{"Report":[ {"source":"08434599494","division":"Car Insurance","totalCalls":5, "chargeableCalls":23},
{"source":"08434599172","division":"Car Insurance","totalCalls":512,"chargeableCalls":44},
{"source":"08434599129","division":"Home Insurance","totalCalls":4, "chargeableCalls":2},
{"source":"08434599215","division":"Home Insurance","totalCalls":234, "chargeableCalls":54},
{"source":"08434599596","division":"Car Insurance","totalCalls":332, "chargeableCalls":266}
]
}
}
问:怎样才能得到想要的输出?
在您的示例中,groupedResults 是一个数组列表。取而代之的是,尝试为一个组创建一个 ViewModel。然后可以使用此 ViewModel 计算总数。例如...
function GroupViewModel(division) {
var self = this;
self.Division = division;
self.Items = ko.observableArray();
self.Count = ko.computed(function() {
var count = 0;
ko.utils.arrayForEach(self.Items(), function(r) { count += r.totalCalls; });
return count;
});
self.ChargeableCount = ko.computed(function() {
var count = 0;
ko.utils.arrayForEach(self.Items(), function(r) { count += r.chargeableCalls; });
return count;
});
}
您也可以简化主 Viewmodel,并将项目推送到 GroupViewModel 中:
function GroupedReportingViewModel() {
var self = this;
self.results = ko.observableArray();
self.groupedResults = ko.computed(function() {
var groups = [];
ko.utils.arrayForEach(self.Results(), function(r) {
var g = ko.utils.arrayFirst(groups, function(g) { return g.Division === r.division; });
if (!g) {
g = new GroupViewModel(r.division);
groups.push(g);
}
g.Items.push(r);
});
return groups;
});
self.TotalCount = ko.computed(function() {
var count = 0;
ko.utils.arrayForEach(self.results(), function(r) { count += r.totalCalls; });
return count;
});
self.TotalChargeableCount = ko.computed(function() {
var count = 0;
ko.utils.arrayForEach(self.results(), function(r) { count += r.chargeableCalls; });
return count;
});
}
最后在您看来,遍历组,然后是项目:
<tbody>
<!-- ko foreach: groupedResults -->
<tr>
<td colspan="3" data-bind="text: Division" class="division"></td>
</tr>
<!-- ko foreach: Items -->
<tr>
<td data-bind="text: source"></td>
<td data-bind="text: totalCalls"></td>
<td data-bind="text: chargeableCalls"></td>
</tr>
<!-- /ko -->
<tr>
<td>Total Calls</td>
<td data-bind="text: Count"></td>
<td>Total Chargeable:</td>
<td data-bind="text: ChargeableCount"></td>
</tr>
<!-- /ko -->
<tr>
<td>Total Calls All</td>
<td data-bind="text: TotalCount"></td>
<td>Total Chargeable All</td>
<td data-bind="text: TotalChargeableCount"></td>
</tr>
</tbody>
具有数据绑定的 table 当前如下所示:
Source Calls ChargeableCalls
Car Insurance
08434599111 3 2
08934345122 2 1
Home Insurance
08734599333 3 2
08034345555 2 1
所需的输出 应该像下面的例子,table 应该包含 Calls
和 ChargeableCalls
的总值分组table.
Calls
和 ChargeableCalls
的除法和总值
Source Calls ChargeableCalls
Car Insurance
08434599154 3 2
08934345555 2 1
Total Calls 5 Total CC 3
Home Insurance
08434599154 6 3
08934345555 1 0
Total Calls 7 Total CC 3
Total Calls All 24 Total CC All 12
以下是 table 中的绑定:
<table class="table table-condensed" id="reportData">
<thead>
<tr>
<th>Source</th>
<th>TotalCalls</th>
<th>ChargeableCalls</th>
</tr>
</thead>
<tbody data-bind="foreach: groups">
<!-- ko foreach: $root.getGroup($data) -->
<tr data-bind="if: $index() == 0">
<td colspan="3" data-bind="text: division" class="division"></td>
</tr>
<tr>
<td data-bind="text: source"></td>
<td data-bind="text: totalCalls"></td>
<td data-bind="text: chargeableCalls"></td>
</tr>
<!-- /ko -->
</tbody>
这是我的视图模型:
function GroupedReportingViewModel() {
var self = this;
self.results = ko.observableArray();
self.groupedResults = {};
self.getGroup = function (group) {
return self.groupedResults[group];
};
self.groupedResultsC = ko.computed(function () {
self.groupedResults = {};
ko.utils.arrayForEach(self.results(), function (r) {
if (!self.groupedResults[r.division]) self.groupedResults[r.division] = [];
self.groupedResults[r.division].push(r);
});
return self.groupedResults;
});
self.groups = ko.computed(function () {
var g = [];
for (x in self.groupedResultsC())
g.push(x);
return g;_
});
}
var model = new GroupedReportingViewModel();
ko.applyBindings(model);
results
observableArray 从 ajax 响应中填充,如下所示:
success: function (jsondata) {
model.results(jsondata["Data"]["Report"]);
}
jsondata
对象如下所示:
{"Data":
{"Report":[ {"source":"08434599494","division":"Car Insurance","totalCalls":5, "chargeableCalls":23},
{"source":"08434599172","division":"Car Insurance","totalCalls":512,"chargeableCalls":44},
{"source":"08434599129","division":"Home Insurance","totalCalls":4, "chargeableCalls":2},
{"source":"08434599215","division":"Home Insurance","totalCalls":234, "chargeableCalls":54},
{"source":"08434599596","division":"Car Insurance","totalCalls":332, "chargeableCalls":266}
]
}
}
问:怎样才能得到想要的输出?
在您的示例中,groupedResults 是一个数组列表。取而代之的是,尝试为一个组创建一个 ViewModel。然后可以使用此 ViewModel 计算总数。例如...
function GroupViewModel(division) {
var self = this;
self.Division = division;
self.Items = ko.observableArray();
self.Count = ko.computed(function() {
var count = 0;
ko.utils.arrayForEach(self.Items(), function(r) { count += r.totalCalls; });
return count;
});
self.ChargeableCount = ko.computed(function() {
var count = 0;
ko.utils.arrayForEach(self.Items(), function(r) { count += r.chargeableCalls; });
return count;
});
}
您也可以简化主 Viewmodel,并将项目推送到 GroupViewModel 中:
function GroupedReportingViewModel() {
var self = this;
self.results = ko.observableArray();
self.groupedResults = ko.computed(function() {
var groups = [];
ko.utils.arrayForEach(self.Results(), function(r) {
var g = ko.utils.arrayFirst(groups, function(g) { return g.Division === r.division; });
if (!g) {
g = new GroupViewModel(r.division);
groups.push(g);
}
g.Items.push(r);
});
return groups;
});
self.TotalCount = ko.computed(function() {
var count = 0;
ko.utils.arrayForEach(self.results(), function(r) { count += r.totalCalls; });
return count;
});
self.TotalChargeableCount = ko.computed(function() {
var count = 0;
ko.utils.arrayForEach(self.results(), function(r) { count += r.chargeableCalls; });
return count;
});
}
最后在您看来,遍历组,然后是项目:
<tbody>
<!-- ko foreach: groupedResults -->
<tr>
<td colspan="3" data-bind="text: Division" class="division"></td>
</tr>
<!-- ko foreach: Items -->
<tr>
<td data-bind="text: source"></td>
<td data-bind="text: totalCalls"></td>
<td data-bind="text: chargeableCalls"></td>
</tr>
<!-- /ko -->
<tr>
<td>Total Calls</td>
<td data-bind="text: Count"></td>
<td>Total Chargeable:</td>
<td data-bind="text: ChargeableCount"></td>
</tr>
<!-- /ko -->
<tr>
<td>Total Calls All</td>
<td data-bind="text: TotalCount"></td>
<td>Total Chargeable All</td>
<td data-bind="text: TotalChargeableCount"></td>
</tr>
</tbody>