5

Die Tabelle mit den Daten-Bindings sieht derzeit wie folgt:Knockout.js: Summe gruppiert Werte innerhalb der Tabelle und foreach

Source  Calls  ChargeableCalls 

Car Insurance 
08434599154  3   2 
08934345555  2   1 

Home Insurance 
08434599154  3   2 
08934345555  2   1 

Die gewünschte Ausgangs wie in dem unten Beispiel sein sollte, sollte die Tabelle enthalten Gesamtwerte für und ChargeableCalls gruppiert nach Division, und Gesamtwerte für alle und ChargeableCalls innerhalb der Tabelle.

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 

Hier sind die Bindungen innerhalb der Tabelle:

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

Hier ist meine 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); 

Die results observableArray von einer Ajax-Antwort bevölkert wird, wie unten:

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

Das jsondata Objekt sieht unten wie:

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

F: Wie kann ich den gewünschten Ausgang erreichen?

Antwort

4

In Ihrem Beispiel ist groupedResults eine Liste von Arrays. Versuchen Sie stattdessen, ein ViewModel für eine Gruppe zu erstellen. Dieses ViewModel kann dann zur Berechnung der Summen verwendet werden. Zum Beispiel ...

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

Sie können Ihr Hauptansichtsmodell auch, und drücken Sie die Elemente in die GroupViewModel statt vereinfachen:

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

Schließlich Ihrer Ansicht nach durchlaufen die Gruppen, und dann die Elemente :

<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

Sorry, ein letzter Kritikpunkt, 'groupedResults' muss ein Array sein. Sie können nicht auf ein Objekt "foreach". –

+0

Behoben. Wenn der Datensatz groß wäre, würde ich es effizienter machen, aber das ist einfach. – Richard

+0

Es funktioniert super, danke Kumpel! Das Hinzufügen der Summe aller Werte für "Anrufe insgesamt" und "Gebührenpflichtige Anrufe insgesamt" innerhalb der Tabelle würde ein zusätzliches ViewModel erfordern. – alex