Skip to content

Commit 29a7b6c

Browse files
alisasanibarminmeh
andauthored
[DataGridPro] Fix pinned columns order in column management (#17950)
Co-authored-by: Armin Mehinovic <armin@mui.com>
1 parent 34847f9 commit 29a7b6c

File tree

3 files changed

+118
-6
lines changed

3 files changed

+118
-6
lines changed

packages/x-data-grid-pro/src/hooks/features/columnPinning/useGridColumnPinningPreProcessors.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { RefObject } from '@mui/x-internals/types';
33
import {
44
GridPipeProcessor,
55
useGridRegisterPipeProcessor,
6-
gridVisiblePinnedColumnDefinitionsSelector,
6+
gridExistingPinnedColumnSelector,
77
} from '@mui/x-data-grid/internals';
88
import { DataGridProProcessedProps } from '../../../models/dataGridProProps';
99
import { GridPrivateApiPro } from '../../../models/gridApiPro';
@@ -30,13 +30,13 @@ export const useGridColumnPinningPreProcessors = (
3030
const savedState = apiRef.current.state;
3131
apiRef.current.state = { ...savedState, columns: columnsState as unknown as any };
3232

33-
const visibleColumns = gridVisiblePinnedColumnDefinitionsSelector(apiRef);
33+
const pinnedColumns = gridExistingPinnedColumnSelector(apiRef);
3434

3535
apiRef.current.state = savedState;
3636
// HACK: Ends here //
3737

38-
const leftPinnedColumns = visibleColumns.left.map((c) => c.field);
39-
const rightPinnedColumns = visibleColumns.right.map((c) => c.field);
38+
const leftPinnedColumns = pinnedColumns.left;
39+
const rightPinnedColumns = pinnedColumns.right;
4040

4141
let newOrderedFields: string[];
4242
const allPinnedColumns = [...leftPinnedColumns, ...rightPinnedColumns];

packages/x-data-grid-pro/src/tests/columnPinning.DataGridPro.test.tsx

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,4 +720,104 @@ describe('<DataGridPro /> - Column pinning', () => {
720720
expect(ageCellColumnGroupHeader.textContent).to.equal('Basic info');
721721
});
722722
});
723+
724+
describe('pinned columns order in column management', () => {
725+
it('should keep pinned column order in column management panel when toggling columns', async () => {
726+
const { user } = render(
727+
<TestCase
728+
rows={[{ id: 1, brand: 'Nike' }]}
729+
columns={[{ field: 'id' }, { field: 'brand' }]}
730+
showToolbar
731+
initialState={{
732+
pinnedColumns: {
733+
left: ['brand'],
734+
},
735+
}}
736+
/>,
737+
);
738+
739+
await user.click(screen.getByRole('button', { name: 'Columns' }));
740+
741+
const columnCheckboxes = screen.getAllByRole('checkbox');
742+
743+
expect(columnCheckboxes[0]).to.have.attribute('name', 'brand');
744+
expect(columnCheckboxes[1]).to.have.attribute('name', 'id');
745+
746+
await user.click(columnCheckboxes[1]);
747+
748+
await user.click(screen.getByRole('button', { name: 'Columns' }));
749+
await user.click(screen.getByRole('button', { name: 'Columns' }));
750+
751+
const checkboxesAfterToggle = screen.getAllByRole('checkbox');
752+
753+
expect(checkboxesAfterToggle[0]).to.have.attribute('name', 'brand');
754+
expect(checkboxesAfterToggle[1]).to.have.attribute('name', 'id');
755+
});
756+
757+
it('should keep pinned column order in column management panel when clicking show/hide all checkbox', async () => {
758+
const { user } = render(
759+
<TestCase
760+
rows={[{ id: 0, brand: 'Nike' }]}
761+
columns={[{ field: 'id' }, { field: 'brand' }]}
762+
showToolbar
763+
initialState={{
764+
pinnedColumns: {
765+
left: ['brand'],
766+
},
767+
}}
768+
/>,
769+
);
770+
771+
await user.click(screen.getByRole('button', { name: 'Columns' }));
772+
773+
const columnCheckboxes = screen.getAllByRole('checkbox');
774+
775+
expect(columnCheckboxes[0]).to.have.attribute('name', 'brand');
776+
expect(columnCheckboxes[1]).to.have.attribute('name', 'id');
777+
778+
await user.click(columnCheckboxes[columnCheckboxes.length - 1]);
779+
780+
await user.click(screen.getByRole('button', { name: 'Columns' }));
781+
await user.click(screen.getByRole('button', { name: 'Columns' }));
782+
783+
const checkboxesAfterToggle = screen.getAllByRole('checkbox');
784+
expect(checkboxesAfterToggle[0]).to.have.attribute('name', 'brand');
785+
expect(checkboxesAfterToggle[1]).to.have.attribute('name', 'id');
786+
});
787+
788+
it('should update column order when pinned columns are updated', async () => {
789+
const { user } = render(
790+
<TestCase
791+
rows={[{ id: 0, brand: 'Nike', price: 100 }]}
792+
columns={[{ field: 'id' }, { field: 'brand' }, { field: 'price' }]}
793+
showToolbar
794+
initialState={{
795+
pinnedColumns: {},
796+
columns: {
797+
columnVisibilityModel: { id: false },
798+
},
799+
}}
800+
/>,
801+
);
802+
803+
await user.click(screen.getByRole('button', { name: 'Columns' }));
804+
805+
const columnCheckboxes = screen.getAllByRole('checkbox');
806+
807+
expect(columnCheckboxes[0]).to.have.attribute('name', 'id');
808+
expect(columnCheckboxes[1]).to.have.attribute('name', 'brand');
809+
expect(columnCheckboxes[2]).to.have.attribute('name', 'price');
810+
811+
await act(() => {
812+
apiRef.current?.pinColumn('brand', GridPinnedColumnPosition.LEFT);
813+
apiRef.current?.pinColumn('id', GridPinnedColumnPosition.RIGHT);
814+
});
815+
816+
const checkboxesAfterPinning = screen.getAllByRole('checkbox');
817+
818+
expect(checkboxesAfterPinning[0]).to.have.attribute('name', 'brand');
819+
expect(checkboxesAfterPinning[1]).to.have.attribute('name', 'price');
820+
expect(checkboxesAfterPinning[2]).to.have.attribute('name', 'id');
821+
});
822+
});
723823
});

packages/x-data-grid/src/hooks/features/columns/gridColumnsSelector.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,18 @@ export const gridPinnedColumnsSelector = createRootSelector(
9696
(state: GridStateCommunity) => state.pinnedColumns,
9797
);
9898

99+
/**
100+
* Get all existing pinned columns. Place the columns on the side that depends on the rtl state.
101+
* @category Pinned Columns
102+
* @ignore - Do not document
103+
*/
104+
export const gridExistingPinnedColumnSelector = createSelectorMemoized(
105+
gridPinnedColumnsSelector,
106+
gridColumnFieldsSelector,
107+
gridIsRtlSelector,
108+
(model, orderedFields, isRtl) => filterMissingColumns(model, orderedFields, isRtl),
109+
);
110+
99111
/**
100112
* Get the visible pinned columns.
101113
* @category Visible Columns
@@ -106,7 +118,7 @@ export const gridVisiblePinnedColumnDefinitionsSelector = createSelectorMemoized
106118
gridVisibleColumnFieldsSelector,
107119
gridIsRtlSelector,
108120
(columnsState, model, visibleColumnFields, isRtl) => {
109-
const visiblePinnedFields = filterVisibleColumns(model, visibleColumnFields, isRtl);
121+
const visiblePinnedFields = filterMissingColumns(model, visibleColumnFields, isRtl);
110122
const visiblePinnedColumns = {
111123
left: visiblePinnedFields.left.map((field) => columnsState.lookup[field]),
112124
right: visiblePinnedFields.right.map((field) => columnsState.lookup[field]),
@@ -115,7 +127,7 @@ export const gridVisiblePinnedColumnDefinitionsSelector = createSelectorMemoized
115127
},
116128
);
117129

118-
function filterVisibleColumns(
130+
function filterMissingColumns(
119131
pinnedColumns: GridPinnedColumnFields,
120132
columns: string[],
121133
invert?: boolean,

0 commit comments

Comments
 (0)