Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataGrid] Allow to control visibility of columns shown in ColumnsPanel #8401

Merged
merged 5 commits into from Apr 3, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,54 @@
import * as React from 'react';
import {
DataGridPremium,
GridToolbar,
useKeepGroupedColumnsHidden,
useGridApiRef,
} from '@mui/x-data-grid-premium';
import { useDemoData } from '@mui/x-data-grid-generator';

const hiddenFields = ['__row_group_by_columns_group__', 'status'];

const getTogglableColumns = (columns) => {
return columns
.filter((column) => !hiddenFields.includes(column.field))
.map((column) => column.field);
};

export default function ColumnSelectorGridCustomizeColumns() {
const { data } = useDemoData({
dataSet: 'Commodity',
rowLength: 10,
maxColumns: 10,
});

const apiRef = useGridApiRef();

const initialState = useKeepGroupedColumnsHidden({
apiRef,
initialState: {
...data.initialState,
rowGrouping: {
model: ['status'],
},
},
});

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPremium
apiRef={apiRef}
{...data}
initialState={initialState}
slots={{
toolbar: GridToolbar,
}}
slotProps={{
columnsPanel: {
getTogglableColumns,
},
}}
/>
</div>
);
}
@@ -0,0 +1,55 @@
import * as React from 'react';
import {
DataGridPremium,
GridToolbar,
GridColDef,
useKeepGroupedColumnsHidden,
useGridApiRef,
} from '@mui/x-data-grid-premium';
import { useDemoData } from '@mui/x-data-grid-generator';

const hiddenFields = ['__row_group_by_columns_group__', 'status'];

const getTogglableColumns = (columns: GridColDef[]) => {
return columns
.filter((column) => !hiddenFields.includes(column.field))
.map((column) => column.field);
};

export default function ColumnSelectorGridCustomizeColumns() {
const { data } = useDemoData({
dataSet: 'Commodity',
rowLength: 10,
maxColumns: 10,
});

const apiRef = useGridApiRef();

const initialState = useKeepGroupedColumnsHidden({
apiRef,
initialState: {
...data.initialState,
rowGrouping: {
model: ['status'],
},
},
});

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPremium
apiRef={apiRef}
{...data}
initialState={initialState}
slots={{
toolbar: GridToolbar,
}}
slotProps={{
columnsPanel: {
getTogglableColumns,
},
}}
/>
</div>
);
}
@@ -0,0 +1,13 @@
<DataGridPremium
apiRef={apiRef}
{...data}
initialState={initialState}
slots={{
toolbar: GridToolbar,
}}
slotProps={{
columnsPanel: {
getTogglableColumns,
},
}}
/>
26 changes: 26 additions & 0 deletions docs/data/data-grid/column-visibility/column-visibility.md
Expand Up @@ -60,6 +60,32 @@ The user can then choose which columns are visible using the _Columns_ button.

{{"demo": "ColumnSelectorGrid.js", "bg": "inline"}}

### Customize the list of columns in panel

To show or hide specific columns in the column visibility panel, use the `slotProps.columnsPanel.getTogglableColumns` prop. It should return an array of column field names.

```tsx
const getTogglableColumns = (columns: GridColDef[]) => {
// hide the column with field `id` from list of togglable columns
return columns
.filter((column) => column.field !== 'id')
.map((column) => column.field);
};

<DataGrid
slots={{
toolbar: GridToolbar,
}}
slotProps={{
columnsPanel: {
getTogglableColumns,
},
}}
/>;
```

{{"demo": "ColumnSelectorGridCustomizeColumns.js", "bg": "inline"}}

### Disable action buttons

To disable `Hide all` or `Show all` buttons in the column visibility panel, pass `disableHideAllButton` or `disableShowAllButton` to `slotProps.columnsPanel`.
Expand Down
Expand Up @@ -83,6 +83,14 @@ export interface GridColumnsPanelProps extends GridPanelWrapperProps {
* @default false
*/
disableShowAllButton?: boolean;
/**
* Returns the list of togglable columns.
* If used, only those columns will be displayed in the panel
* which are passed as the return value of the function.
* @param {GridColDef[]} columns The `ColDef` list of all columns.
* @returns {GridColDef['field'][]} The list of togglable columns' field names.
*/
getTogglableColumns?: (columns: GridColDef[]) => GridColDef['field'][];
}

const collator = new Intl.Collator();
Expand All @@ -109,6 +117,7 @@ function GridColumnsPanel(props: GridColumnsPanelProps) {
autoFocusSearchField = true,
disableHideAllButton = false,
disableShowAllButton = false,
getTogglableColumns,
...other
} = props;

Expand Down Expand Up @@ -163,12 +172,23 @@ function GridColumnsPanel(props: GridColumnsPanelProps) {
);

const currentColumns = React.useMemo(() => {
const togglableColumns = getTogglableColumns ? getTogglableColumns(sortedColumns) : null;
cherniavskii marked this conversation as resolved.
Show resolved Hide resolved

if (!searchValue) {
return sortedColumns;
return togglableColumns
? sortedColumns.filter(({ field }) => togglableColumns.includes(field))
: sortedColumns;
}
const searchValueToCheck = searchValue.toLowerCase();
return sortedColumns.filter((column) => searchPredicate(column, searchValueToCheck));
}, [sortedColumns, searchValue, searchPredicate]);
return sortedColumns.filter((column) => {
if (togglableColumns) {
return (
togglableColumns.includes(column.field) && searchPredicate(column, searchValueToCheck)
);
}
return searchPredicate(column, searchValueToCheck);
});
}, [sortedColumns, searchValue, searchPredicate, getTogglableColumns]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opportunity to simplify this code?

const togglableColumns = getTogglableColumns ? getTogglableColumns(sortedColumns) : null;
const togglableSortedColumns = togglableColumns
  ? sortedColumns.filter(({ field }) => togglableColumns.includes(field))
  : sortedColumns;
if (!searchValue) {
  return togglableSortedColumns;
}
const searchValueToCheck = searchValue.toLowerCase();
return togglableSortedColumns.filter((column) => searchPredicate(column, searchValueToCheck));

What do you think?


const firstSwitchRef = React.useRef<HTMLInputElement>(null);

Expand Down Expand Up @@ -277,6 +297,14 @@ GridColumnsPanel.propTypes = {
autoFocusSearchField: PropTypes.bool,
disableHideAllButton: PropTypes.bool,
disableShowAllButton: PropTypes.bool,
/**
* Returns the list of togglable columns.
* If used, only those columns will be displayed in the panel
* which are passed as the return value of the function.
* @param {GridColDef[]} columns The `ColDef` list of all columns.
* @returns {GridColDef['field'][]} The list of togglable columns' field names.
*/
getTogglableColumns: PropTypes.func,
searchPredicate: PropTypes.func,
slotProps: PropTypes.object,
sort: PropTypes.oneOf(['asc', 'desc']),
Expand Down
Expand Up @@ -310,4 +310,25 @@ describe('<DataGridPro /> - Columns Visibility', () => {
fireEvent.click(screen.getByRole('button', { name: 'Select columns' }));
expect(screen.queryByRole('button', { name: 'Show all' })).to.equal(null);
});

it('should control columns shown in columns panel using `getTogglableColumns` prop', () => {
const getTogglableColumns = (cols: GridColDef[]) =>
cols.filter((column) => column.field !== 'idBis').map((column) => column.field);
render(
<TestDataGrid
slots={{
toolbar: GridToolbar,
}}
slotProps={{
columnsPanel: {
getTogglableColumns,
},
}}
/>,
);

fireEvent.click(screen.getByRole('button', { name: 'Select columns' }));
expect(screen.queryByRole('checkbox', { name: 'id' })).not.to.equal(null);
expect(screen.queryByRole('checkbox', { name: 'idBis' })).to.equal(null);
});
});