From 3f7adc56671df7f2f08ebaf39de0ef580229f1c5 Mon Sep 17 00:00:00 2001 From: Armin Mehinovic Date: Sun, 21 Apr 2024 12:53:11 +0200 Subject: [PATCH 1/5] Add util to retrieve fields from a group header via data-fields attribute --- packages/x-data-grid/src/utils/domUtils.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/x-data-grid/src/utils/domUtils.ts b/packages/x-data-grid/src/utils/domUtils.ts index cbf4071ea77a7..ce83ee25501c3 100644 --- a/packages/x-data-grid/src/utils/domUtils.ts +++ b/packages/x-data-grid/src/utils/domUtils.ts @@ -71,6 +71,11 @@ export function findHeaderElementFromField(elem: Element, field: string): HTMLDi return elem.querySelector(`[data-field="${field}"]`)!; } +export function getFieldsFromGroupHeaderElem(colCellEl: Element): string[] { + const found = colCellEl.getAttribute('data-fields')!.match(/^\|-(.+)-\|$/); + return found ? found[1].split('-|-') : []; +} + export function findGroupHeaderElementsFromField(elem: Element, field: string): Element[] { return Array.from(elem.querySelectorAll(`[data-fields*="|-${field}-|"]`) ?? []); } From 2d745268551332ef2913fcbab8ffd76031d0f7b7 Mon Sep 17 00:00:00 2001 From: Armin Mehinovic Date: Sun, 21 Apr 2024 12:59:24 +0200 Subject: [PATCH 2/5] Recalculate group header widths after column widths were adjusted based on the flex values and the remaining space --- .../columnResize/useGridColumnResize.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/x-data-grid/src/hooks/features/columnResize/useGridColumnResize.tsx b/packages/x-data-grid/src/hooks/features/columnResize/useGridColumnResize.tsx index 7595d08380aa5..e4d3c51d905e6 100644 --- a/packages/x-data-grid/src/hooks/features/columnResize/useGridColumnResize.tsx +++ b/packages/x-data-grid/src/hooks/features/columnResize/useGridColumnResize.tsx @@ -12,6 +12,7 @@ import { findRightPinnedCellsBeforeCol, getFieldFromHeaderElem, findHeaderElementFromField, + getFieldsFromGroupHeaderElem, findGroupHeaderElementsFromField, findGridHeader, findGridCells, @@ -428,6 +429,24 @@ export const useGridColumnResize = ( if (refs.colDef) { apiRef.current.setColumnWidth(refs.colDef.field, refs.colDef.width!); logger.debug(`Updating col ${refs.colDef.field} with new width: ${refs.colDef.width}`); + + const columnsState = gridColumnsStateSelector(apiRef.current.state); + refs.groupHeaderElements!.forEach((element) => { + const fields = getFieldsFromGroupHeaderElem(element); + const div = element as HTMLDivElement; + + const newWidth = fields.reduce((acc, field) => { + if (columnsState.columnVisibilityModel[field] !== false) { + return acc + columnsState.lookup[field].computedWidth; + } + return acc; + }, 0); + const finalWidth: `${number}px` = `${newWidth}px`; + + div.style.width = finalWidth; + div.style.minWidth = finalWidth; + div.style.maxWidth = finalWidth; + }); } stopResizeEventTimeout.start(0, () => { From dd662cf84a582ae0edd1538e4619810ad8109e48 Mon Sep 17 00:00:00 2001 From: Armin Mehinovic Date: Sun, 21 Apr 2024 20:15:38 +0200 Subject: [PATCH 3/5] Add e2e test --- test/e2e/fixtures/DataGrid/ResizeWithFlex.tsx | 35 +++++++++++++ test/e2e/index.test.ts | 49 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 test/e2e/fixtures/DataGrid/ResizeWithFlex.tsx diff --git a/test/e2e/fixtures/DataGrid/ResizeWithFlex.tsx b/test/e2e/fixtures/DataGrid/ResizeWithFlex.tsx new file mode 100644 index 0000000000000..dd88d80c11365 --- /dev/null +++ b/test/e2e/fixtures/DataGrid/ResizeWithFlex.tsx @@ -0,0 +1,35 @@ +import * as React from 'react'; +import { DataGrid } from '@mui/x-data-grid'; + +const columns = [ + { field: 'column1', flex: 1 }, + { field: 'column2', flex: 1 }, + { field: 'column3', flex: 1 }, + { field: 'column4', flex: 0 }, + { field: 'column5', flex: 0 }, +]; + +const columnGroupingModel = [ + { + groupId: 'group1', + children: [ + { field: 'column1' }, + { + groupId: 'group1.1', + children: [{ field: 'column2' }, { field: 'column3' }, { field: 'column4' }], + }, + ], + }, + { + groupId: 'group2', + children: [{ field: 'column5' }], + }, +]; + +export default function ResizeWithFlex() { + return ( +
+ +
+ ); +} diff --git a/test/e2e/index.test.ts b/test/e2e/index.test.ts index 501bc94fcd3a2..67941fbd3c5af 100644 --- a/test/e2e/index.test.ts +++ b/test/e2e/index.test.ts @@ -11,6 +11,7 @@ import { BrowserContextOptions, BrowserType, WebError, + Locator, } from '@playwright/test'; import { pickersTextFieldClasses } from '@mui/x-date-pickers/PickersTextField'; import { pickersSectionListClasses } from '@mui/x-date-pickers/PickersSectionList'; @@ -538,6 +539,54 @@ async function initializeEnvironment( await sleep(200); expect(thrownError).to.equal(null); }); + + // https://github.com/mui/mui-x/issues/12290 + it('should properly set the width of a group header if the resize happened in a group with fluid columns', async () => { + await renderFixture('DataGrid/ResizeWithFlex'); + + const headers = await page.locator('.MuiDataGrid-columnHeaders > div').all(); + const columnHeader = headers.pop()!; + + const columns = columnHeader.locator('.MuiDataGrid-columnHeader'); + const separators = await columnHeader + .locator('.MuiDataGrid-columnSeparator--resizable') + .all(); + + const moveSeparator = async (separator: Locator) => { + const boundingBox = (await separator?.boundingBox())!; + const x = boundingBox.x + boundingBox.width / 2; + const y = boundingBox.y + boundingBox.height / 2; + + await page.mouse.move(x, y, { steps: 5 }); + await page.mouse.down(); + await page.mouse.move(x - 20, y, { steps: 5 }); + await page.mouse.up(); + }; + + await moveSeparator(separators[0]); + await moveSeparator(separators[1]); + + const groupHeaderWidth = await headers[0] + .locator('.MuiDataGrid-columnHeader--filledGroup') + .first() + .evaluate((node) => node.clientWidth); + const subGroupHeaderWidth = await headers[1] + .locator('.MuiDataGrid-columnHeader--filledGroup') + .first() + .evaluate((node) => node.clientWidth); + + const groupHeaderColumnsTotalWidth = await columns.evaluateAll((columns) => + // last column is not part of the group + columns.slice(0, -1).reduce((acc, column) => acc + column.clientWidth, 0), + ); + const subGroupHeaderColumnsTotalWidth = await columns.evaluateAll((columns) => + // first and last columns are not part of the sub-group + columns.slice(1, -1).reduce((acc, column) => acc + column.clientWidth, 0), + ); + + expect(groupHeaderWidth).to.equal(groupHeaderColumnsTotalWidth); + expect(subGroupHeaderWidth).to.equal(subGroupHeaderColumnsTotalWidth); + }); }); describe('', () => { From 45bd6835e3aace6e2f67f05632353fdeede416c8 Mon Sep 17 00:00:00 2001 From: Armin Mehinovic Date: Sun, 21 Apr 2024 21:05:13 +0200 Subject: [PATCH 4/5] Fix test lint issue --- test/e2e/index.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/e2e/index.test.ts b/test/e2e/index.test.ts index 67941fbd3c5af..84fbf4bd4b849 100644 --- a/test/e2e/index.test.ts +++ b/test/e2e/index.test.ts @@ -575,13 +575,13 @@ async function initializeEnvironment( .first() .evaluate((node) => node.clientWidth); - const groupHeaderColumnsTotalWidth = await columns.evaluateAll((columns) => + const groupHeaderColumnsTotalWidth = await columns.evaluateAll((elements) => // last column is not part of the group - columns.slice(0, -1).reduce((acc, column) => acc + column.clientWidth, 0), + elements.slice(0, -1).reduce((acc, element) => acc + element.clientWidth, 0), ); - const subGroupHeaderColumnsTotalWidth = await columns.evaluateAll((columns) => + const subGroupHeaderColumnsTotalWidth = await columns.evaluateAll((elements) => // first and last columns are not part of the sub-group - columns.slice(1, -1).reduce((acc, column) => acc + column.clientWidth, 0), + elements.slice(1, -1).reduce((acc, element) => acc + element.clientWidth, 0), ); expect(groupHeaderWidth).to.equal(groupHeaderColumnsTotalWidth); From 4cf98fc1d96d9a914e75863c8b9d21c1815eaa78 Mon Sep 17 00:00:00 2001 From: Armin Mehinovic Date: Tue, 23 Apr 2024 09:55:12 +0200 Subject: [PATCH 5/5] Avoid regexp for better readability Co-authored-by: Andrew Cherniavskii Signed-off-by: Armin Mehinovic --- packages/x-data-grid/src/utils/domUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/x-data-grid/src/utils/domUtils.ts b/packages/x-data-grid/src/utils/domUtils.ts index ce83ee25501c3..dd27e95e58108 100644 --- a/packages/x-data-grid/src/utils/domUtils.ts +++ b/packages/x-data-grid/src/utils/domUtils.ts @@ -72,8 +72,8 @@ export function findHeaderElementFromField(elem: Element, field: string): HTMLDi } export function getFieldsFromGroupHeaderElem(colCellEl: Element): string[] { - const found = colCellEl.getAttribute('data-fields')!.match(/^\|-(.+)-\|$/); - return found ? found[1].split('-|-') : []; + const fieldsString = colCellEl.getAttribute('data-fields'); + return fieldsString?.startsWith('|-') ? fieldsString!.slice(2, -2).split('-|-') : []; } export function findGroupHeaderElementsFromField(elem: Element, field: string): Element[] {