5

tabeli z danymi-wiązania obecnie wygląda następująco:Knockout.js: suma zgrupowane wartości w tabeli i foreach

Source  Calls  ChargeableCalls 

Car Insurance 
08434599154  3   2 
08934345555  2   1 

Home Insurance 
08434599154  3   2 
08934345555  2   1 

sygnał wyjściowy powinno być jak na poniższym przykładzie Tabela powinna zawierać wartości całkowite dla Calls i ChargeableCalls pogrupowane według dzielenia i wartości całkowite dla wszystkich Calls i ChargeableCalls w tabeli.

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 

Oto Wiązania w tabeli:

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

Oto mój 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 zostaje wypełniana od ajax odpowiedzi, jak poniżej:

success: function (jsondata) { 
     model.results(jsondata["Data"]["Report"]); 
} 

Przedmiotem jsondata wygląda jak poniżej:

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

Q: W jaki sposób można osiągnąć pożądany wynik?

Odpowiedz

4

W twoim przykładzie, groupedResults jest listą tablic. Zamiast tego spróbuj utworzyć ViewModel dla grupy. Ten ViewModel może być następnie użyty do obliczenia sumy. Na przykład ...

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; 
    }); 
} 

Można uprościć swoje główne ViewModel zbyt, i przesunąć elementy do GroupViewModel Zamiast:

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; 
    }); 
} 

Wreszcie Państwa zdaniem iterację grup, a następnie elementy :

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

Przepraszam, ostatnia krytyka, 'groupedResults' musi być tablicą. Nie można "foreach" na obiekcie. –

+0

Naprawiono. Jeśli zbiór danych byłby duży, sprawiłbym, że byłby on bardziej wydajny, ale jest to proste. – Richard

+0

Działa wspaniale, dzięki kolego! Dodanie sumy wszystkich wartości dla "Total Calls" i "Total Chargeable Calls" w tabeli wymagałoby dodatkowego ViewModel? – alex