Skip to main content

Summary Row

The summary row places aggregate results directly under the columns they describe. The sample starts sorted by Net contribution descending and keeps the header filter row visible so you can immediately see how aggregates respond to the current filtered view. A grid can mix aggregate functions across columns, and users can change the active aggregate at runtime when allowAggregateChange is enabled.

Financial summary
Loading FDC sample…
final financials = FdcDataSet(
fields: <FdcFieldDef>[
const FdcIntegerField(name: 'id', label: 'ID', isKey: true),
const FdcStringField(name: 'region', label: 'Region', size: 40),
const FdcDecimalField(
name: 'gross_revenue',
label: 'Gross revenue',
precision: 14,
scale: 2,
),
const FdcDecimalField(
name: 'operating_expenses',
label: 'Operating expenses',
precision: 14,
scale: 2,
),
const FdcDecimalField(
name: 'commission_rate',
label: 'Commission %',
precision: 6,
scale: 2,
),
FdcDecimalField(
name: 'commission_amount',
label: 'Commission amount',
precision: 14,
scale: 2,
calculatedValue: (row) {
final revenue = row.numValue('gross_revenue') ?? 0;
final rate = row.numValue('commission_rate') ?? 0;
return revenue * rate / 100;
},
),
FdcDecimalField(
name: 'net_contribution',
label: 'Net contribution',
precision: 14,
scale: 2,
calculatedValue: (row) {
final revenue = row.numValue('gross_revenue') ?? 0;
final expenses = row.numValue('operating_expenses') ?? 0;
final commission = row.numValue('commission_amount') ?? 0;
return revenue - expenses - commission;
},
),
],
adapter: FdcMemoryDataAdapter(rows: financialRows),
);

await financials.open();
await financials.sort.set(const <FdcDataSetSort>[
FdcDataSetSort(
fieldName: 'net_contribution',
sortType: FdcSortType.descending,
),
]);

FdcGrid(
dataSet: financials,
options: const FdcGridOptions(autoEdit: true),
header: const FdcGridHeader(
filters: FdcGridHeaderFilters(
visible: true,
initiallyVisible: true,
),
),
columns: const <FdcGridColumn<dynamic>>[
FdcTextColumn<dynamic>(
fieldName: 'region',
width: 150,
),
FdcDecimalColumn<dynamic>(
fieldName: 'gross_revenue',
width: 170,
prefixText: r'$ ',
summary: FdcColumnSummary(
aggregate: FdcAggregate.sum,
label: 'Total',
allowAggregateChange: true,
),
),
FdcDecimalColumn<dynamic>(
fieldName: 'operating_expenses',
width: 180,
prefixText: r'$ ',
summary: FdcColumnSummary(
aggregate: FdcAggregate.sum,
label: 'Total',
allowAggregateChange: true,
),
),
FdcDecimalColumn<dynamic>(
fieldName: 'commission_rate',
width: 145,
suffixText: ' %',
summary: FdcColumnSummary(
aggregate: FdcAggregate.avg,
label: 'Avg',
allowAggregateChange: true,
),
),
FdcDecimalColumn<dynamic>(
fieldName: 'commission_amount',
width: 175,
prefixText: r'$ ',
summary: FdcColumnSummary(
aggregate: FdcAggregate.sum,
label: 'Total',
allowAggregateChange: true,
),
),
FdcDecimalColumn<dynamic>(
fieldName: 'net_contribution',
width: 180,
prefixText: r'$ ',
summary: FdcColumnSummary(
aggregate: FdcAggregate.sum,
label: 'Total',
allowAggregateChange: true,
),
),
],
);

The sample models regional financial performance. Gross revenue and operating expenses are stored values, Commission % is an editable percentage, and the two columns on the right are calculated from the row data.

Configure a summary cell

Attach FdcColumnSummary to any supported column:

FdcDecimalColumn<dynamic>(
fieldName: 'gross_revenue',
prefixText: r'$ ',
summary: const FdcColumnSummary(
aggregate: FdcAggregate.sum,
label: 'Total',
allowAggregateChange: true,
),
)

aggregate selects the initial operation. label controls the text rendered beside the value, and allowAggregateChange enables the summary-cell menu so the user can switch to another supported aggregate.

The sample deliberately mixes aggregate semantics:

  • Gross revenue — sum
  • Operating expenses — sum
  • Commission % — average
  • Commission amount — sum
  • Net contribution — sum

That distinction matters. Percentages often make more sense as an average, while monetary contribution columns usually need totals.

User interaction

When allowAggregateChange is enabled, open the summary cell menu and select another aggregate. The grid recomputes and redraws that summary cell immediately.

Try changing Gross revenue or Net contribution from Sum to Avg, Min, or Max. The row data does not change; only the aggregate operation used by that summary cell changes.

Supported operations depend on the column data type. Unsupported combinations are not applied.

Calculated financial columns

Calculated fields belong to the dataset schema, not to presentation code. In this sample the commission amount is derived from revenue and the percentage field:

FdcDecimalField(
name: 'commission_amount',
precision: 14,
scale: 2,
calculatedValue: (row) {
final revenue = row.numValue('gross_revenue') ?? 0;
final rate = row.numValue('commission_rate') ?? 0;
return revenue * rate / 100;
},
)

The rightmost Net contribution field then uses the calculated commission amount:

FdcDecimalField(
name: 'net_contribution',
precision: 14,
scale: 2,
calculatedValue: (row) {
final revenue = row.numValue('gross_revenue') ?? 0;
final expenses = row.numValue('operating_expenses') ?? 0;
final commission = row.numValue('commission_amount') ?? 0;
return revenue - expenses - commission;
},
)

Because these are dataset calculated fields, changing revenue, expenses, or the commission percentage refreshes the dependent values. Their summary cells then aggregate the refreshed calculated values.

Summary row visibility

The summary panel remains hidden when no visible column has an active summary aggregate. You do not need a separate global switch just to make a configured summary visible.

For dataset-level aggregate queries and paged aggregate behavior, see DataSet Aggregates.