【问题标题】:Knockout.js: Sum grouped values within table and foreachKnockout.js:对表和 foreach 中的分组值求和
【发布时间】:2015-05-22 19:42:37
【问题描述】:

数据绑定表目前如下所示:

Source        Calls     ChargeableCalls

Car Insurance
08434599111     3            2
08934345122     2            1

Home Insurance
08734599333     3            2
08034345555     2            1

期望的输出应该像下面的例子一样,该表应该包含CallsChargeableCalls按部门分组的总值,以及所有Calls和@987654325的总值@ 在表格内。

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 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>

这是我的 ViewModel:

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}
              ]
    }
}

问:我怎样才能达到想要的输出?

【问题讨论】:

    标签: javascript html knockout.js knockout-2.0


    【解决方案1】:

    在您的示例中,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; 
        });
    }
    

    您也可以简化主视图模型,并将项目推送到 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>
    

    【讨论】:

    • 对不起,最后一个批评,groupedResults 必须是一个数组。你不能在对象上foreach
    • 已修复。如果数据集很大,我会提高效率,但这很简单。
    • 效果很好,谢谢伙计!在表中添加 Total CallsTotal Chargeable Calls 的所有值的总和需要额外的 ViewModel?
    • 不,只是在顶层视图模型上添加一个计算
    • 感谢您的更新。你能告诉我如果数据集随着时间的推移变得越来越大,这将如何执行?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多