DevExtreme v24.2 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

React Data Grid - Column Chooser

To change column visibility at runtime, set the columnChooser.enabled property to true. To make certain that a given column(s) always stay visible, set the columns[].allowHiding property to false.

Backend API
import React, { useCallback, useState } from 'react'; import { DataGrid, Column, ColumnChooser, ColumnChooserSearch, ColumnChooserSelection, Position, } from 'devextreme-react/data-grid'; import { SelectBox, SelectBoxTypes } from 'devextreme-react/select-box'; import { CheckBox, CheckBoxTypes } from 'devextreme-react/check-box'; import { employees } from './data.ts'; const columnChooserModes: { key: 'select' | 'dragAndDrop', name: string, }[] = [{ key: 'dragAndDrop', name: 'Drag and drop', }, { key: 'select', name: 'Select', }]; const searchEditorOptions = { placeholder: 'Search column' }; const columnChooserModeLabel = { 'aria-label': 'Column Chooser Mode' }; const App = () => { const [mode, setMode] = useState(columnChooserModes[1].key); const [searchEnabled, setSearchEnabled] = useState(true); const [allowSelectAll, setAllowSelectAll] = useState(true); const [selectByClick, setSelectByClick] = useState(true); const [recursive, setRecursive] = useState(true); const isDragMode = mode === columnChooserModes[0].key; const onModeValueChanged = useCallback((e: SelectBoxTypes.ValueChangedEvent) => { setMode(e.value); }, []); const onSearchEnabledValueChanged = useCallback((e: CheckBoxTypes.ValueChangedEvent) => { setSearchEnabled(e.value); }, []); const onAllowSelectAllValueChanged = useCallback((e: CheckBoxTypes.ValueChangedEvent) => { setAllowSelectAll(e.value); }, []); const onSelectByClickValueChanged = useCallback((e: CheckBoxTypes.ValueChangedEvent) => { setSelectByClick(e.value); }, []); const onRecursiveValueChanged = useCallback((e: CheckBoxTypes.ValueChangedEvent) => { setRecursive(e.value); }, []); return ( <div> <DataGrid id="employees" dataSource={employees} keyExpr="ID" columnAutoWidth={true} showRowLines={true} width="100%" showBorders={true} > <Column dataField='FirstName' allowHiding={false} /> <Column dataField='LastName' /> <Column dataField='Position' /> <Column dataField='City' /> <Column dataField='State' /> <Column caption="Contacts"> <Column dataField="MobilePhone" allowHiding={false} /> <Column dataField="Email" /> <Column dataField="Skype" visible={false} /> </Column> <Column dataField="HireDate" dataType="date" /> <ColumnChooser height='340px' enabled={true} mode={mode} > <Position my="right top" at="right bottom" of=".dx-datagrid-column-chooser-button" /> <ColumnChooserSearch enabled={searchEnabled} editorOptions={searchEditorOptions} /> <ColumnChooserSelection allowSelectAll={allowSelectAll} selectByClick={selectByClick} recursive={recursive} /> </ColumnChooser> </DataGrid> <div className="options"> <div className="caption">Options</div> <div className="selectboxes-container"> <div className="option"> <span>Column chooser mode</span> &nbsp; <SelectBox items={columnChooserModes} value={mode} valueExpr="key" inputAttr={columnChooserModeLabel} displayExpr="name" onValueChanged={onModeValueChanged} /> </div> </div> <div className='checkboxes-container'> <div className="option"> <CheckBox id="searchEnabled" defaultValue={searchEnabled} text="Search enabled" onValueChanged={onSearchEnabledValueChanged} /> </div> <div className="option"> <CheckBox id="allowSelectAll" defaultValue={allowSelectAll} text="Allow select all" onValueChanged={onAllowSelectAllValueChanged} disabled={isDragMode} /> </div> <div className="option"> <CheckBox id="selectByClick" defaultValue={selectByClick} text="Select by click" onValueChanged={onSelectByClickValueChanged} disabled={isDragMode} /> </div> <div className="option"> <CheckBox id="recursive" defaultValue={recursive} text="Recursive" onValueChanged={onRecursiveValueChanged} disabled={isDragMode} /> </div> </div> </div> </div> ); }; export default App;
import React, { useCallback, useState } from 'react'; import { DataGrid, Column, ColumnChooser, ColumnChooserSearch, ColumnChooserSelection, Position, } from 'devextreme-react/data-grid'; import { SelectBox } from 'devextreme-react/select-box'; import { CheckBox } from 'devextreme-react/check-box'; import { employees } from './data.js'; const columnChooserModes = [ { key: 'dragAndDrop', name: 'Drag and drop', }, { key: 'select', name: 'Select', }, ]; const searchEditorOptions = { placeholder: 'Search column' }; const columnChooserModeLabel = { 'aria-label': 'Column Chooser Mode' }; const App = () => { const [mode, setMode] = useState(columnChooserModes[1].key); const [searchEnabled, setSearchEnabled] = useState(true); const [allowSelectAll, setAllowSelectAll] = useState(true); const [selectByClick, setSelectByClick] = useState(true); const [recursive, setRecursive] = useState(true); const isDragMode = mode === columnChooserModes[0].key; const onModeValueChanged = useCallback((e) => { setMode(e.value); }, []); const onSearchEnabledValueChanged = useCallback((e) => { setSearchEnabled(e.value); }, []); const onAllowSelectAllValueChanged = useCallback((e) => { setAllowSelectAll(e.value); }, []); const onSelectByClickValueChanged = useCallback((e) => { setSelectByClick(e.value); }, []); const onRecursiveValueChanged = useCallback((e) => { setRecursive(e.value); }, []); return ( <div> <DataGrid id="employees" dataSource={employees} keyExpr="ID" columnAutoWidth={true} showRowLines={true} width="100%" showBorders={true} > <Column dataField="FirstName" allowHiding={false} /> <Column dataField="LastName" /> <Column dataField="Position" /> <Column dataField="City" /> <Column dataField="State" /> <Column caption="Contacts"> <Column dataField="MobilePhone" allowHiding={false} /> <Column dataField="Email" /> <Column dataField="Skype" visible={false} /> </Column> <Column dataField="HireDate" dataType="date" /> <ColumnChooser height="340px" enabled={true} mode={mode} > <Position my="right top" at="right bottom" of=".dx-datagrid-column-chooser-button" /> <ColumnChooserSearch enabled={searchEnabled} editorOptions={searchEditorOptions} /> <ColumnChooserSelection allowSelectAll={allowSelectAll} selectByClick={selectByClick} recursive={recursive} /> </ColumnChooser> </DataGrid> <div className="options"> <div className="caption">Options</div> <div className="selectboxes-container"> <div className="option"> <span>Column chooser mode</span> &nbsp; <SelectBox items={columnChooserModes} value={mode} valueExpr="key" inputAttr={columnChooserModeLabel} displayExpr="name" onValueChanged={onModeValueChanged} /> </div> </div> <div className="checkboxes-container"> <div className="option"> <CheckBox id="searchEnabled" defaultValue={searchEnabled} text="Search enabled" onValueChanged={onSearchEnabledValueChanged} /> </div> <div className="option"> <CheckBox id="allowSelectAll" defaultValue={allowSelectAll} text="Allow select all" onValueChanged={onAllowSelectAllValueChanged} disabled={isDragMode} /> </div> <div className="option"> <CheckBox id="selectByClick" defaultValue={selectByClick} text="Select by click" onValueChanged={onSelectByClickValueChanged} disabled={isDragMode} /> </div> <div className="option"> <CheckBox id="recursive" defaultValue={recursive} text="Recursive" onValueChanged={onRecursiveValueChanged} disabled={isDragMode} /> </div> </div> </div> </div> ); }; export default App;
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.tsx'; ReactDOM.render( <App />, document.getElementById('app'), );
export const employees = [{ ID: 1, FirstName: 'John', LastName: 'Heart', Position: 'CEO', BirthDate: '1964/03/16', HireDate: '1995/01/15', Title: 'Mr.', Address: '351 S Hill St.', City: 'Los Angeles', State: 'California', Zipcode: 90013, Email: 'jheart@dx-email.com', Skype: 'jheartDXskype', HomePhone: '(213) 555-9208', DepartmentID: 6, MobilePhone: '(213) 555-9392', }, { ID: 2, FirstName: 'Olivia', LastName: 'Peyton', Position: 'Sales Assistant', BirthDate: '1981/06/03', HireDate: '2012/05/14', Title: 'Mrs.', Address: '807 W Paseo Del Mar', City: 'Los Angeles', State: 'California', Zipcode: 90036, Email: 'oliviap@dx-email.com', Skype: 'oliviapDXskype', HomePhone: '(310) 555-2728', DepartmentID: 5, MobilePhone: '(818) 555-2387', }, { ID: 3, FirstName: 'Robert', LastName: 'Reagan', Position: 'CMO', BirthDate: '1974/09/07', HireDate: '2002/11/08', Title: 'Mr.', Address: '4 Westmoreland Pl.', City: 'Bentonville', State: 'Arkansas', Zipcode: 91103, Email: 'robertr@dx-email.com', Skype: 'robertrDXskype', HomePhone: '(818) 555-2438', DepartmentID: 6, MobilePhone: '(818) 555-2387', }, { ID: 4, FirstName: 'Greta', LastName: 'Sims', Position: 'HR Manager', BirthDate: '1977/11/22', HireDate: '1998/04/23', Title: 'Ms.', Address: '1700 S Grandview Dr.', State: 'Georgia', City: 'Atlanta', Zipcode: 91803, Email: 'gretas@dx-email.com', Skype: 'gretasDXskype', HomePhone: '(818) 555-0976', DepartmentID: 5, MobilePhone: '(818) 555-6546', }, { ID: 5, FirstName: 'Brett', LastName: 'Wade', Position: 'IT Manager', BirthDate: '1968/12/01', HireDate: '2009/03/06', Title: 'Mr.', Address: '1120 Old Mill Rd.', State: 'Idaho', City: 'Boise', Zipcode: 91108, Email: 'brettw@dx-email.com', Skype: 'brettwDXskype', HomePhone: '(626) 555-5985', DepartmentID: 7, MobilePhone: '(626) 555-0358', }, { ID: 6, FirstName: 'Sandra', LastName: 'Johnson', Position: 'Controller', BirthDate: '1974/11/15', HireDate: '2005/05/11', Title: 'Mrs.', Address: '4600 N Virginia Rd.', State: 'Utah', City: 'Beaver', Zipcode: 90807, Email: 'sandraj@dx-email.com', Skype: 'sandrajDXskype', HomePhone: '(562) 555-8272', DepartmentID: 5, MobilePhone: '(562) 555-2082', }, { ID: 7, FirstName: 'Kevin', LastName: 'Carter', Position: 'Shipping Manager', BirthDate: '1978/01/09', HireDate: '2009/08/11', Title: 'Mr.', Address: '424 N Main St.', State: 'California', City: 'San Diego', Zipcode: 90012, Email: 'kevinc@dx-email.com', Skype: 'kevincDXskype', HomePhone: '(213) 555-8038', DepartmentID: 3, MobilePhone: '(213) 555-2840', }, { ID: 8, FirstName: 'Cynthia', LastName: 'Stanwick', Position: 'HR Assistant', BirthDate: '1985/06/05', HireDate: '2008/03/24', Title: 'Ms.', Address: '2211 Bonita Dr.', City: 'Little Rock', State: 'Arkansas', Zipcode: 90265, Email: 'cindys@dx-email.com', Skype: 'cindysDXskype', HomePhone: '(818) 555-6808', DepartmentID: 4, MobilePhone: '(818) 555-6655', }, { ID: 9, FirstName: 'Kent', LastName: 'Samuelson', Position: 'Ombudsman', BirthDate: '1972/09/11', HireDate: '2009/04/22', Title: 'Dr.', Address: '12100 Mora Dr', City: 'St. Louis', State: 'Missouri', Zipcode: 90272, Email: 'kents@dx-email.com', Skype: 'kentsDXskype', HomePhone: '(562) 555-1328', DepartmentID: 26, MobilePhone: '(562) 555-9282', }, { ID: 10, FirstName: 'Taylor', LastName: 'Riley', Position: 'Network Admin', BirthDate: '1982/08/14', HireDate: '2012/04/14', Title: 'Mr.', Address: '7776 Torreyson Dr', City: 'San Jose', State: 'California', Zipcode: 90012, Email: 'taylorr@dx-email.com', Skype: 'taylorrDXskype', HomePhone: '(310) 555-9712', DepartmentID: 5, MobilePhone: '(310) 555-7276', }];
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);
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.js'; ReactDOM.render(<App />, document.getElementById('app'));
export const employees = [ { ID: 1, FirstName: 'John', LastName: 'Heart', Position: 'CEO', BirthDate: '1964/03/16', HireDate: '1995/01/15', Title: 'Mr.', Address: '351 S Hill St.', City: 'Los Angeles', State: 'California', Zipcode: 90013, Email: 'jheart@dx-email.com', Skype: 'jheartDXskype', HomePhone: '(213) 555-9208', DepartmentID: 6, MobilePhone: '(213) 555-9392', }, { ID: 2, FirstName: 'Olivia', LastName: 'Peyton', Position: 'Sales Assistant', BirthDate: '1981/06/03', HireDate: '2012/05/14', Title: 'Mrs.', Address: '807 W Paseo Del Mar', City: 'Los Angeles', State: 'California', Zipcode: 90036, Email: 'oliviap@dx-email.com', Skype: 'oliviapDXskype', HomePhone: '(310) 555-2728', DepartmentID: 5, MobilePhone: '(818) 555-2387', }, { ID: 3, FirstName: 'Robert', LastName: 'Reagan', Position: 'CMO', BirthDate: '1974/09/07', HireDate: '2002/11/08', Title: 'Mr.', Address: '4 Westmoreland Pl.', City: 'Bentonville', State: 'Arkansas', Zipcode: 91103, Email: 'robertr@dx-email.com', Skype: 'robertrDXskype', HomePhone: '(818) 555-2438', DepartmentID: 6, MobilePhone: '(818) 555-2387', }, { ID: 4, FirstName: 'Greta', LastName: 'Sims', Position: 'HR Manager', BirthDate: '1977/11/22', HireDate: '1998/04/23', Title: 'Ms.', Address: '1700 S Grandview Dr.', State: 'Georgia', City: 'Atlanta', Zipcode: 91803, Email: 'gretas@dx-email.com', Skype: 'gretasDXskype', HomePhone: '(818) 555-0976', DepartmentID: 5, MobilePhone: '(818) 555-6546', }, { ID: 5, FirstName: 'Brett', LastName: 'Wade', Position: 'IT Manager', BirthDate: '1968/12/01', HireDate: '2009/03/06', Title: 'Mr.', Address: '1120 Old Mill Rd.', State: 'Idaho', City: 'Boise', Zipcode: 91108, Email: 'brettw@dx-email.com', Skype: 'brettwDXskype', HomePhone: '(626) 555-5985', DepartmentID: 7, MobilePhone: '(626) 555-0358', }, { ID: 6, FirstName: 'Sandra', LastName: 'Johnson', Position: 'Controller', BirthDate: '1974/11/15', HireDate: '2005/05/11', Title: 'Mrs.', Address: '4600 N Virginia Rd.', State: 'Utah', City: 'Beaver', Zipcode: 90807, Email: 'sandraj@dx-email.com', Skype: 'sandrajDXskype', HomePhone: '(562) 555-8272', DepartmentID: 5, MobilePhone: '(562) 555-2082', }, { ID: 7, FirstName: 'Kevin', LastName: 'Carter', Position: 'Shipping Manager', BirthDate: '1978/01/09', HireDate: '2009/08/11', Title: 'Mr.', Address: '424 N Main St.', State: 'California', City: 'San Diego', Zipcode: 90012, Email: 'kevinc@dx-email.com', Skype: 'kevincDXskype', HomePhone: '(213) 555-8038', DepartmentID: 3, MobilePhone: '(213) 555-2840', }, { ID: 8, FirstName: 'Cynthia', LastName: 'Stanwick', Position: 'HR Assistant', BirthDate: '1985/06/05', HireDate: '2008/03/24', Title: 'Ms.', Address: '2211 Bonita Dr.', City: 'Little Rock', State: 'Arkansas', Zipcode: 90265, Email: 'cindys@dx-email.com', Skype: 'cindysDXskype', HomePhone: '(818) 555-6808', DepartmentID: 4, MobilePhone: '(818) 555-6655', }, { ID: 9, FirstName: 'Kent', LastName: 'Samuelson', Position: 'Ombudsman', BirthDate: '1972/09/11', HireDate: '2009/04/22', Title: 'Dr.', Address: '12100 Mora Dr', City: 'St. Louis', State: 'Missouri', Zipcode: 90272, Email: 'kents@dx-email.com', Skype: 'kentsDXskype', HomePhone: '(562) 555-1328', DepartmentID: 26, MobilePhone: '(562) 555-9282', }, { ID: 10, FirstName: 'Taylor', LastName: 'Riley', Position: 'Network Admin', BirthDate: '1982/08/14', HireDate: '2012/04/14', Title: 'Mr.', Address: '7776 Torreyson Dr', City: 'San Jose', State: 'California', Zipcode: 90012, Email: 'taylorr@dx-email.com', Skype: 'taylorrDXskype', HomePhone: '(310) 555-9712', DepartmentID: 5, MobilePhone: '(310) 555-7276', }, ];
<!DOCTYPE html> <html lang="en"> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/24.2.3/css/dx.light.css" /> <link rel="stylesheet" type="text/css" href="styles.css" /> <script src="https://unpkg.com/core-js@2.6.12/client/shim.min.js"></script> <script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script> <script type="text/javascript" src="config.js"></script> <script type="text/javascript"> System.import("./index.tsx"); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"></div> </div> </body> </html>
#employees { max-height: 440px; } .options { padding: 20px; margin-top: 20px; background-color: rgba(191, 191, 191, 0.15); } .caption { font-size: 18px; font-weight: 500; } .option { margin-top: 10px; } .option > span { margin-right: 10px; } .option > .dx-selectbox { display: inline-block; vertical-align: middle; } .selectbox-container { display: flex; } .checkboxes-container { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; margin-top: 15px; } .checkboxes-container > .option { margin: 10px 30px 10px 0; width: 200px; }

To display the column chooser, click the appropriate toolbar button above the DataGrid. You can specify the column chooser's position via the columnChooser.position property. The manner in which users can display/hide columns depends on columnChooser.mode:

  • "dragAndDrop"
    Users can drag and drop column headers to and from the column chooser.

  • "select"
    Users can select and deselect check boxes with column names.

In "select" mode, you can choose whether parent element selection affects child/nested elements. Use the selection.recursive property for this purpose.

If the column chooser contains multiple hidden columns, you can enable the DevExtreme Grid’s column search UI. Assign true to the search.enabled property for this purpose.

In this demo, use the check boxes below the DataGrid to toggle search and selection features.

To hide a column in code, set the columns[].visible property to false.