If you have technical questions, please create a support ticket in the DevExpress Support Center.
import React from 'react';
import DataGrid, {
Column, Selection, Paging, Summary, TotalItem, DataGridTypes,
} from 'devextreme-react/data-grid';
import { orders } from './data.ts';
const startupSelectedKeys = [1, 4, 7];
const calculateSelectedRow = (options: DataGridTypes.CustomSummaryInfo) => {
if (options.name === 'SelectedRowsSummary') {
if (options.summaryProcess === 'start') {
options.totalValue = 0;
}
const isRowSelected = options.component.isRowSelected(options.value?.ID);
if (options.summaryProcess === 'calculate' && isRowSelected) {
options.totalValue += options.value.SaleAmount;
}
}
};
const onSelectionChanged = (e: DataGridTypes.SelectionChangedEvent) => e.component.refresh(true);
const App = () => (
<DataGrid
id="gridContainer"
defaultSelectedRowKeys={startupSelectedKeys}
onSelectionChanged={onSelectionChanged}
dataSource={orders}
keyExpr="ID"
showBorders={true}>
<Paging enabled={false} />
<Selection mode="multiple" />
<Column dataField="OrderNumber" width={130} caption="Invoice Number" />
<Column dataField="OrderDate" dataType="date" />
<Column dataField="Employee" />
<Column dataField="CustomerStoreCity" caption="City" />
<Column dataField="CustomerStoreState" caption="State" />
<Column dataField="SaleAmount" width={160} alignment="right" format="currency" />
<Summary calculateCustomSummary={calculateSelectedRow}>
<TotalItem
name="SelectedRowsSummary"
summaryType="custom"
valueFormat="currency"
displayFormat="Sum: {0}"
showInColumn="SaleAmount" />
</Summary>
</DataGrid>
);
export default App;
xxxxxxxxxx
import React from 'react';
import DataGrid, {
Column,
Selection,
Paging,
Summary,
TotalItem,
} from 'devextreme-react/data-grid';
import { orders } from './data.js';
const startupSelectedKeys = [1, 4, 7];
const calculateSelectedRow = (options) => {
if (options.name === 'SelectedRowsSummary') {
if (options.summaryProcess === 'start') {
options.totalValue = 0;
}
const isRowSelected = options.component.isRowSelected(options.value?.ID);
if (options.summaryProcess === 'calculate' && isRowSelected) {
options.totalValue += options.value.SaleAmount;
}
}
};
const onSelectionChanged = (e) => e.component.refresh(true);
const App = () => (
<DataGrid
id="gridContainer"
defaultSelectedRowKeys={startupSelectedKeys}
onSelectionChanged={onSelectionChanged}
dataSource={orders}
keyExpr="ID"
showBorders={true}
>
<Paging enabled={false} />
<Selection mode="multiple" />
<Column
dataField="OrderNumber"
width={130}
caption="Invoice Number"
/>
<Column
dataField="OrderDate"
dataType="date"
/>
<Column dataField="Employee" />
<Column
dataField="CustomerStoreCity"
caption="City"
/>
<Column
dataField="CustomerStoreState"
caption="State"
/>
<Column
dataField="SaleAmount"
width={160}
alignment="right"
format="currency"
/>
<Summary calculateCustomSummary={calculateSelectedRow}>
<TotalItem
name="SelectedRowsSummary"
summaryType="custom"
valueFormat="currency"
displayFormat="Sum: {0}"
showInColumn="SaleAmount"
/>
</Summary>
</DataGrid>
);
export default App;
xxxxxxxxxx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
ReactDOM.render(
<App />,
document.getElementById('app'),
);
xxxxxxxxxx
export const orders = [{
ID: 1,
OrderNumber: 35703,
OrderDate: '2014-04-10',
SaleAmount: 11800,
Terms: '15 Days',
TotalAmount: 12175,
CustomerStoreState: 'California',
CustomerStoreCity: 'Los Angeles',
Employee: 'Harv Mudd',
}, {
ID: 4,
OrderNumber: 35711,
OrderDate: '2014-01-12',
SaleAmount: 16050,
Terms: '15 Days',
TotalAmount: 16550,
CustomerStoreState: 'California',
CustomerStoreCity: 'San Jose',
Employee: 'Jim Packard',
}, {
ID: 5,
OrderNumber: 35714,
OrderDate: '2014-01-22',
SaleAmount: 14750,
Terms: '15 Days',
TotalAmount: 15250,
CustomerStoreState: 'Nevada',
CustomerStoreCity: 'Las Vegas',
Employee: 'Harv Mudd',
}, {
ID: 7,
OrderNumber: 35983,
OrderDate: '2014-02-07',
SaleAmount: 3725,
Terms: '15 Days',
TotalAmount: 3850,
CustomerStoreState: 'Colorado',
CustomerStoreCity: 'Denver',
Employee: 'Todd Hoffman',
}, {
ID: 9,
OrderNumber: 36987,
OrderDate: '2014-03-11',
SaleAmount: 14200,
Terms: '15 Days',
TotalAmount: 14800,
CustomerStoreState: 'Utah',
CustomerStoreCity: 'Salt Lake City',
Employee: 'Clark Morgan',
}, {
ID: 11,
OrderNumber: 38466,
OrderDate: '2014-03-01',
SaleAmount: 7800,
Terms: '15 Days',
TotalAmount: 8200,
CustomerStoreState: 'California',
CustomerStoreCity: 'Los Angeles',
Employee: 'Harv Mudd',
}, {
ID: 15,
OrderNumber: 39874,
OrderDate: '2014-02-04',
SaleAmount: 9050,
Terms: '30 Days',
TotalAmount: 19100,
CustomerStoreState: 'Nevada',
CustomerStoreCity: 'Las Vegas',
Employee: 'Harv Mudd',
}, {
ID: 18,
OrderNumber: 42847,
OrderDate: '2014-02-15',
SaleAmount: 20400,
Terms: '30 Days',
TotalAmount: 20800,
CustomerStoreState: 'Wyoming',
CustomerStoreCity: 'Casper',
Employee: 'Todd Hoffman',
}, {
ID: 19,
OrderNumber: 43982,
OrderDate: '2014-05-29',
SaleAmount: 6050,
Terms: '30 Days',
TotalAmount: 6250,
CustomerStoreState: 'Utah',
CustomerStoreCity: 'Salt Lake City',
Employee: 'Clark Morgan',
}, {
ID: 29,
OrderNumber: 56272,
OrderDate: '2014-02-06',
SaleAmount: 15850,
Terms: '30 Days',
TotalAmount: 16350,
CustomerStoreState: 'Utah',
CustomerStoreCity: 'Salt Lake City',
Employee: 'Clark Morgan',
}, {
ID: 30,
OrderNumber: 57429,
OrderDate: '2013-12-31',
SaleAmount: 11050,
Terms: '30 Days',
TotalAmount: 11400,
CustomerStoreState: 'Arizona',
CustomerStoreCity: 'Phoenix',
Employee: 'Clark Morgan',
}, {
ID: 32,
OrderNumber: 58292,
OrderDate: '2014-05-13',
SaleAmount: 13500,
Terms: '15 Days',
TotalAmount: 13800,
CustomerStoreState: 'California',
CustomerStoreCity: 'Los Angeles',
Employee: 'Harv Mudd',
}];
xxxxxxxxxx
window.exports = window.exports || {};
window.config = {
transpiler: 'ts',
typescriptOptions: {
module: 'system',
emitDecoratorMetadata: true,
experimentalDecorators: true,
jsx: 'react',
},
meta: {
'react': {
'esModule': true,
},
'typescript': {
'exports': 'ts',
},
'devextreme/time_zone_utils.js': {
'esModule': true,
},
'devextreme/localization.js': {
'esModule': true,
},
'devextreme/viz/palette.js': {
'esModule': true,
},
'openai': {
'esModule': true,
},
},
paths: {
'npm:': 'https://unpkg.com/',
'bundles:': 'bundles/',
'externals:': 'bundles/externals/',
},
defaultExtension: 'js',
map: {
'ts': 'npm:plugin-typescript@8.0.0/lib/plugin.js',
'typescript': 'npm:typescript@4.2.4/lib/typescript.js',
'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js',
'react': 'npm:react@17.0.2/umd/react.development.js',
'react-dom': 'npm:react-dom@17.0.2/umd/react-dom.development.js',
'prop-types': 'npm:prop-types/prop-types.js',
'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js',
'luxon': 'npm:luxon@3.4.4/build/global/luxon.min.js',
'es6-object-assign': 'npm:es6-object-assign',
'devextreme': 'npm:devextreme@link:../../packages/devextreme/artifacts/npm/devextreme/cjs',
'devextreme-react': 'npm:devextreme-react@link:../../packages/devextreme-react/npm/cjs',
'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js',
'devexpress-diagram': 'npm:devexpress-diagram@2.2.5/dist/dx-diagram.js',
'devexpress-gantt': 'npm:devexpress-gantt@4.1.54/dist/dx-gantt.js',
'@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12',
'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js',
'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js',
'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js',
'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js',
'inferno-hydrate': 'npm:inferno-hydrate/dist/inferno-hydrate.min.js',
'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js',
'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js',
'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js',
'devextreme-cldr-data': 'npm:devextreme-cldr-data@1.0.3',
// SystemJS plugins
'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js',
'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js',
// Prettier
'prettier/standalone': 'npm:prettier@2.8.8/standalone.js',
'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js',
},
packages: {
'devextreme': {
defaultExtension: 'js',
},
'devextreme-react': {
main: 'index.js',
},
'devextreme/events/utils': {
main: 'index',
},
'devextreme/localization/messages': {
format: 'json',
defaultExtension: 'json',
},
'devextreme/events': {
main: 'index',
},
'es6-object-assign': {
main: './index.js',
defaultExtension: 'js',
},
},
packageConfigPaths: [
'npm:@devextreme/*/package.json',
'npm:@devextreme/runtime@3.0.12/inferno/package.json',
],
babelOptions: {
sourceMaps: false,
stage0: true,
react: true,
},
};
System.config(window.config);
xxxxxxxxxx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
ReactDOM.render(<App />, document.getElementById('app'));
xxxxxxxxxx
export const orders = [
{
ID: 1,
OrderNumber: 35703,
OrderDate: '2014-04-10',
SaleAmount: 11800,
Terms: '15 Days',
TotalAmount: 12175,
CustomerStoreState: 'California',
CustomerStoreCity: 'Los Angeles',
Employee: 'Harv Mudd',
},
{
ID: 4,
OrderNumber: 35711,
OrderDate: '2014-01-12',
SaleAmount: 16050,
Terms: '15 Days',
TotalAmount: 16550,
CustomerStoreState: 'California',
CustomerStoreCity: 'San Jose',
Employee: 'Jim Packard',
},
{
ID: 5,
OrderNumber: 35714,
OrderDate: '2014-01-22',
SaleAmount: 14750,
Terms: '15 Days',
TotalAmount: 15250,
CustomerStoreState: 'Nevada',
CustomerStoreCity: 'Las Vegas',
Employee: 'Harv Mudd',
},
{
ID: 7,
OrderNumber: 35983,
OrderDate: '2014-02-07',
SaleAmount: 3725,
Terms: '15 Days',
TotalAmount: 3850,
CustomerStoreState: 'Colorado',
CustomerStoreCity: 'Denver',
Employee: 'Todd Hoffman',
},
{
ID: 9,
OrderNumber: 36987,
OrderDate: '2014-03-11',
SaleAmount: 14200,
Terms: '15 Days',
TotalAmount: 14800,
CustomerStoreState: 'Utah',
CustomerStoreCity: 'Salt Lake City',
Employee: 'Clark Morgan',
},
{
ID: 11,
OrderNumber: 38466,
OrderDate: '2014-03-01',
SaleAmount: 7800,
Terms: '15 Days',
TotalAmount: 8200,
CustomerStoreState: 'California',
CustomerStoreCity: 'Los Angeles',
Employee: 'Harv Mudd',
},
{
ID: 15,
OrderNumber: 39874,
OrderDate: '2014-02-04',
SaleAmount: 9050,
Terms: '30 Days',
TotalAmount: 19100,
CustomerStoreState: 'Nevada',
CustomerStoreCity: 'Las Vegas',
Employee: 'Harv Mudd',
},
{
ID: 18,
OrderNumber: 42847,
OrderDate: '2014-02-15',
SaleAmount: 20400,
Terms: '30 Days',
TotalAmount: 20800,
CustomerStoreState: 'Wyoming',
CustomerStoreCity: 'Casper',
Employee: 'Todd Hoffman',
},
{
ID: 19,
OrderNumber: 43982,
OrderDate: '2014-05-29',
SaleAmount: 6050,
Terms: '30 Days',
TotalAmount: 6250,
CustomerStoreState: 'Utah',
CustomerStoreCity: 'Salt Lake City',
Employee: 'Clark Morgan',
},
{
ID: 29,
OrderNumber: 56272,
OrderDate: '2014-02-06',
SaleAmount: 15850,
Terms: '30 Days',
TotalAmount: 16350,
CustomerStoreState: 'Utah',
CustomerStoreCity: 'Salt Lake City',
Employee: 'Clark Morgan',
},
{
ID: 30,
OrderNumber: 57429,
OrderDate: '2013-12-31',
SaleAmount: 11050,
Terms: '30 Days',
TotalAmount: 11400,
CustomerStoreState: 'Arizona',
CustomerStoreCity: 'Phoenix',
Employee: 'Clark Morgan',
},
{
ID: 32,
OrderNumber: 58292,
OrderDate: '2014-05-13',
SaleAmount: 13500,
Terms: '15 Days',
TotalAmount: 13800,
CustomerStoreState: 'California',
CustomerStoreCity: 'Los Angeles',
Employee: 'Harv Mudd',
},
];
xxxxxxxxxx
<html lang="en">
<head></head>
<body class="dx-viewport">
<div class="demo-container">
<div id="app"></div>
</div>
</body>
</html>
xxxxxxxxxx
#gridContainer {
height: 440px;
margin-bottom: 10px;
}
-
Make sure that the remoteOperations.summary, remoteOperations.groupPaging, or remoteOperations property is not set or set to false.
-
Add a summary configuration object to the summary.groupItems or summary.totalItems array.
-
Set the object's summaryType to "custom".
-
Specify the summary's name. It will be used to identify the summary item within the calculateCustomSummary function in the next step.
-
Calculate the resulting value in the calculateCustomSummary function. Implement the necessary calculation stages. See the function's description for details.
The custom summary in this example calculates the sum of sale amounts for selected rows. To recalculate the resulting value when selection is changed, the code calls the refresh() method in the onSelectionChanged handler.
Client-side custom summaries are suitable for small datasets. If your tests show that client-side calculations result in noticeable lags, we recommend that you use Server-Side Data Aggregation.