Login Register

Summary Rows

Grouping data for summarization requires a simple strategy. We will calculate a summary subrow for every row in the table, then just hide the ones not on a group boundary. So here is some (boring!) numeric data:

{ 
	identifier: 'id',
	label: 'name',
	items: [
        { id:'Q1_06', name: 'Q1 2006', year:2006, quarter:1, sales:345436 },
        { id:'Q2_06', name: 'Q2 2006', year:2006, quarter:2, sales:234525 },
        { id:'Q3_06', name: 'Q3 2006', year:2006, quarter:3, sales:129104 },
        { id:'Q4_06', name: 'Q4 2006', year:2006, quarter:4, sales:-10000 },
        { id:'Q1_07', name: 'Q1 2007', year:2007, quarter:1, sales:-178775 },
        { id:'Q2_07', name: 'Q2 2007', year:2007, quarter:2, sales:286027 },
        { id:'Q3_07', name: 'Q3 2007', year:2007, quarter:3, sales:429546 },
        { id:'Q4_07', name: 'Q4 2007', year:2007, quarter:4, sales:946375 }
    ]
}

To implement our strategy, we first build two functions which supply the total and total label for each totalling subrow.

function getYearlyLabel(inRowIndex) {
            return model.getRow(inRowIndex) ? "Total for " + model.getRow(inRowIndex).year : 'None';
        }
        function getYearlyTotal(inRowIndex) {
            return model.getRow(inRowIndex) ? (yearlyTotal += model.getRow(inRowIndex).sales) : -1;
        }

Next, we make an onAfterRow procedure to hide all the rows that are not after Q4

// inRow is an array of subRows. we hide the summary subRow except for every nth row
function onAfterRow(inDataIndex, inRow) {
    // note that header row inDataIndex == -1
    inRow[1].hidden = true;

    // Before rows 3, 7, 11 turn on display of the total
    if (inDataIndex != -1 && inDataIndex % 4 == 3) {
	yearlyTotal = 0;
        inRow[1].hidden = false;
    }
}

Then we wire it all up in the view definition:

var view1 = {
    onAfterRow: onAfterRow,
	cells: [[
		{name: 'Year/Quarter', field:'name'}, 
		{name: 'Sales', field:'sales'}
	],[
	    // The summary subrow, which will be hidden on most rows
		{name: 'Cell2', get: getYearlyLabel },
		{name: 'Yearly Sales', get:getYearlyTotal, styles:'font-weight:bold;'},
	]]
};

And the summary rows are displayed. Currently this example shows the summary row for all rows. A question is pending on the forums about this, and the example will be fixed accordingly.

Is this really the best way ?

This seems like a really warped way of generating a footer row. How do you know the size of the table to be able to only display footer on last row.

There seems to be multiple issues with this example.

1. I could not find an onAfterRow function . The Turbo grid is using onBeforeRow for processing .
2. Get function on summary sub row getYearlyTotal(inRowIndex) will probably
only get called once, when the subrow is actually going to be displayed. So you cant use it to accumulate the total .

colSpan on first row view def

If I use colSpan on the first row of a view def,
var view = {
cells: [
[
{name: 'R1 C12', field: "r1c1", colSpan: "2"},
{name: 'R1 C3', field: "r1c2"}
],
[
{name: 'R2 C1', field: "r2c1"},
{name: 'R2 C2', field: "r2c2"},
{name: 'R2 C3', field: "r2c3"}
]
]
};

The first 2 columns for all subrows of row disappear. In fact no matter what col I move the colSpan to, it has the same effect. Only seems to work in rows > 1.
Wondering if I can create a 1st row that is hidden to define columns? How do I do that in the view def?

Thanks.

colSpan on first row view def

You might try experimenting with headerstyles/classes, adding "visibility: hidden;" to the columns whose header rows you want to hide. But I'd also suggest you to file a bug about this in dojo trac.

Some notes

Some notes on the example:

  • If I understand correctly, onBeforeRow is guaranteed to be called right before rendering a row, but not in any other situation.
  • The second parameter to onBeforeRow is an array of subrows. The same array is passed to each onBeforeRow call.
  • Due to the above, the attributes (e.g. "hidden") you set in the subrow objects must be re-set in the next onBeforeRow call, otherwise they will change the rendering of all the rows below. The following code caused me some headache:
    function onBeforeRow(inDataIndex, inRow) {
            if (inDataIndex == something) {
                    inRow[0].hidden = true;
            }

    Until I looked at the example more closely and reset the "hidden" attribute.

    function onBeforeRow(inDataIndex, inRow) {
            if (inDataIndex == something) {
                    inRow[0].hidden = true;
            } else {
                    inRow[0].hidden = false;
            }

Showing the subrow on last row only

aakarsh: you should try checking the "last row" status by calling your model object's getRowCount() method in your onBeforeRow callback.