Knockout.js - 如何获取observableArray中另一个属性分组的属性的总和

时间:2014-04-15 20:07:44

标签: javascript knockout.js

我有收费帐户,需要打印每个帐户名称及其总费用。我无法弄清楚如何获得按帐户分组的运行总计。我可以获得不同的帐户名称,并在两个单独的数组中获得每个帐户的总费用。如何获得每个帐户的费用总和(类似于SQL GROUP BY功能)?

的JavaScript

var viewModel = function () {
    var self    = this;
    self.people = ko.observableArray([
        { AccountId: 1, AccountName: 'Acc1', Charge: 10 },
        { AccountId: 2, AccountName: 'Acc2', Charge: 20 },
        { AccountId: 3, AccountName: 'Acc3', Charge: 30 },
        { AccountId: 1, AccountName: 'Acc1', Charge: 10 },
        { AccountId: 1, AccountName: 'Acc1', Charge: 10 },
        { AccountId: 2, AccountName: 'Acc2', Charge: 20 },
        { AccountId: 2, AccountName: 'Acc2', Charge: 20 }
    ]);

    self.headers = [                     
        { title: 'AccountName'  },
        { title: 'AccountTotal' }
    ];                


    self.justAccounts = ko.computed(function () {
        var accounts = ko.utils.arrayMap(self.people(), function (item) {
            return item.AccountName;
        });
        return accounts.sort();
    });

    self.uniqueAccounts = ko.dependentObservable(function () {
        return ko.utils.arrayGetDistinctValues(self.justAccounts()).sort();
    });

    self.AccTotals = ko.computed(function () {
        var result = [];
        ko.utils.arrayForEach(self.uniqueAccounts(), function (acc) {
            var accTotal = 0;
            ko.utils.arrayFilter(self.people(), function (item) {
                if (item.AccountName == acc) {
                    accTotal += item.Charge;
                }
            })
            result.push(accTotal);
        });

        return result;
    });

}

标记

<tr data-bind="foreach: uniqueAccounts">
    <td data-bind="text: $data"></td>                                   
</tr>
<tr data-bind="foreach: AccTotals">
    <td data-bind="text: $data"></td>                                   
</tr>

1 个答案:

答案 0 :(得分:0)

这样的事情会起作用:

self.accounts = ko.computed(function () {
    var acc = {}, accs = [];

    // accumulate accounts, group by name
    ko.utils.arrayForEach(self.people(), function (person) {
        if (!acc.hasOwnProperty(person.AccountName)) {
            acc[person.AccountName] = {
                AccountName: person.AccountName,
                AccountTotal: 0,
                PersonCount: 0
            };
            accs.push(acc[person.AccountName]);
        }
        acc[person.AccountName].PersonCount++;
        acc[person.AccountName].AccountTotal += person.Charge;
    });

    accs.sort(function (a, b) {
        return a.AccountName > b.AccountName;
    });

    return accs;
});

<tr data-bind="foreach: accounts">
    <td data-bind="text: AccountName"></td>                                   
</tr>
<tr data-bind="foreach: accounts">
    <td data-bind="text: AccountTotal"></td>                                   
</tr>

甚至是这个,如果你想利用你的headers数组:

<!-- ko foreach: headers -->
<tr data-bind="foreach: $root.accounts">
    <td data-bind="text: $data[$parent.title]"></td>
</tr>
<!-- /ko -->

P.S。:你不应该再使用dependentObservable,他们会被称为computed