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 应该包含 CallsChargeableCalls 的总值分组table.

中所有 CallsChargeableCalls 的除法和总值
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>