Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/eui/changelogs/upcoming/9030.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
**Bug fixes**

- Fixed `columns` in `EuiDataGrid` not being rendered in the correct order as defined by `columnVisibility.visibleColumns` which resulted in unexpected updates when reordering columns

Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,34 @@ export const useDataGridColumnSelector = (
'allowReorder'
);

const [sortedColumns, setSortedColumns] = useDependentState(
() => availableColumns.map(({ id }) => id),
[availableColumns]
);

const { visibleColumns, setVisibleColumns } = columnVisibility;

const [sortedColumns, setSortedColumns] = useDependentState(() => {
const availableColumnIds = availableColumns.map(({ id }) => id);
const availableSet = new Set(availableColumnIds);
// Filter visibleColumns to only include existing columns
const validVisibleColumns = visibleColumns.filter((id) =>
availableSet.has(id)
);
const visibleSet = new Set(validVisibleColumns);

const result: string[] = [];
let visibleIndex = 0;

for (const columnId of availableColumnIds) {
if (visibleSet.has(columnId)) {
// Replace with next visible column in order
result.push(validVisibleColumns[visibleIndex++]);
} else {
// Keep hidden column in original position
result.push(columnId);
}
}

return result;
// doesn't depend on visibleColumns on purpose to keep it an initial state
}, [availableColumns]);

const visibleColumnIds = useMemo(
() => new Set(visibleColumns),
[visibleColumns]
Expand Down
165 changes: 164 additions & 1 deletion packages/eui/src/components/datagrid/data_grid.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/// <reference types="cypress-real-events" />
/// <reference types="../../../cypress/support" />

import React, { ReactNode } from 'react';
import React, { ReactNode, useState } from 'react';
import {
EuiDataGrid,
EuiDataGridColumn,
Expand Down Expand Up @@ -737,6 +737,169 @@ a, footer\tb, footer
});
});
});

describe('column reordering', () => {
const props = {
...baseProps,
columns: [
{ id: 'a', display: 'First' },
{ id: 'b', display: 'Second' },
{ id: 'c', display: 'Third' },
{ id: 'd', display: 'Fourth' },
],
columnVisibility: {
visibleColumns: ['a', 'b', 'd'],
setVisibleColumns: () => {},
canDragAndDropColumns: true,
},
} as EuiDataGridProps;

const StatefulDataGrid = ({
columns,
columnVisibility,
...rest
}: EuiDataGridProps) => {
const [visibleColumns, setVisibleColumns] = useState(
columnVisibility.visibleColumns
);

return (
<EuiDataGrid
{...rest}
columns={columns ?? []}
columnVisibility={{
...columnVisibility,
visibleColumns,
setVisibleColumns,
}}
// ExclusiveUnion shenanigans :|
aria-label="Testing"
aria-labelledby={undefined}
/>
);
};

it('renders columns in the correct order when `columns` and `visibleColumns` have the same order', () => {
cy.mount(<StatefulDataGrid {...props} />);

cy.get(
'[data-gridcell-column-index="0"][data-gridcell-visible-row-index="-1"] .euiDataGridHeaderCell__content'
).should('have.text', 'First');
cy.get(
'[data-gridcell-column-index="1"][data-gridcell-visible-row-index="-1"] .euiDataGridHeaderCell__content'
).should('have.text', 'Second');
cy.get(
'[data-gridcell-column-index="2"][data-gridcell-visible-row-index="-1"] .euiDataGridHeaderCell__content'
).should('have.text', 'Fourth');

/* checks column selector popover order */
cy.get('[data-test-subj="dataGridColumnSelectorButton"]').click();

cy.get('.euiDataGridColumnSelector__item').eq(0).should('have.text', 'a');
cy.get('.euiDataGridColumnSelector__item').eq(1).should('have.text', 'b');
cy.get('.euiDataGridColumnSelector__item').eq(2).should('have.text', 'c');
cy.get('.euiDataGridColumnSelector__item').eq(3).should('have.text', 'd');

cy.get(
'.euiDataGridColumnSelector__item [data-test-subj="dataGridColumnSelectorToggleColumnVisibility-c"]'
).should('have.attr', 'aria-checked', 'false');
});

it('renders columns in the corect order when `columns` and `visibleColumns` have different orders', () => {
cy.mount(
<StatefulDataGrid
{...props}
columnVisibility={{
...props.columnVisibility,
visibleColumns: ['b', 'd', 'a'],
}}
/>
);

cy.get(
'[data-gridcell-column-index="0"][data-gridcell-visible-row-index="-1"] .euiDataGridHeaderCell__content'
).should('have.text', 'Second');
cy.get(
'[data-gridcell-column-index="1"][data-gridcell-visible-row-index="-1"] .euiDataGridHeaderCell__content'
).should('have.text', 'Fourth');
cy.get(
'[data-gridcell-column-index="2"][data-gridcell-visible-row-index="-1"] .euiDataGridHeaderCell__content'
).should('have.text', 'First');

/* checks column selector popover order */
cy.get('[data-test-subj="dataGridColumnSelectorButton"]').click();

cy.get('.euiDataGridColumnSelector__item').eq(0).should('have.text', 'b');
cy.get('.euiDataGridColumnSelector__item').eq(1).should('have.text', 'd');
cy.get('.euiDataGridColumnSelector__item').eq(2).should('have.text', 'c');
cy.get('.euiDataGridColumnSelector__item').eq(3).should('have.text', 'a');

cy.get(
'.euiDataGridColumnSelector__item [data-test-subj="dataGridColumnSelectorToggleColumnVisibility-c"]'
).should('have.attr', 'aria-checked', 'false');
});

it('reorders columns from the column selector', () => {
cy.mount(<StatefulDataGrid {...props} />);

cy.get('[data-test-subj="dataGridColumnSelectorButton"]').click();

/* reorder column selectors */
cy.get('.euiDataGridColumnSelector__item')
.eq(0)
.realHover()
.realMouseDown({ position: 'center' })
.realMouseMove(0, 0) // start drag
.realMouseMove(0, 120) // move (absolute coordinates)
.realMouseUp();

cy.get('.euiDataGridColumnSelector__item').eq(0).should('have.text', 'b');
cy.get('.euiDataGridColumnSelector__item').eq(1).should('have.text', 'a');
cy.get('.euiDataGridColumnSelector__item').eq(2).should('have.text', 'c');
cy.get('.euiDataGridColumnSelector__item').eq(3).should('have.text', 'd');

cy.get(
'[data-gridcell-column-index="0"][data-gridcell-visible-row-index="-1"] .euiDataGridHeaderCell__content'
).should('have.text', 'Second');
cy.get(
'[data-gridcell-column-index="1"][data-gridcell-visible-row-index="-1"] .euiDataGridHeaderCell__content'
).should('have.text', 'First');
cy.get(
'[data-gridcell-column-index="2"][data-gridcell-visible-row-index="-1"] .euiDataGridHeaderCell__content'
).should('have.text', 'Fourth');
});

it('reorders columns via drag and drop', () => {
cy.mount(<StatefulDataGrid {...props} />);

/* reorder columns*/
cy.get(
'[data-gridcell-column-index="0"][data-gridcell-visible-row-index="-1"]'
)
.realHover()
.realMouseDown({ position: 'center' })
.realMouseMove(0, 0) // start drag
.realMouseMove(250, 50) // move (absolute coordinates)
.realMouseUp();

cy.get(
'[data-gridcell-column-index="0"][data-gridcell-visible-row-index="-1"] .euiDataGridHeaderCell__content'
).should('have.text', 'Second');
cy.get(
'[data-gridcell-column-index="1"][data-gridcell-visible-row-index="-1"] .euiDataGridHeaderCell__content'
).should('have.text', 'Fourth');
cy.get(
'[data-gridcell-column-index="2"][data-gridcell-visible-row-index="-1"] .euiDataGridHeaderCell__content'
).should('have.text', 'First');

cy.get('[data-test-subj="dataGridColumnSelectorButton"]').click();

cy.get('.euiDataGridColumnSelector__item').eq(0).should('have.text', 'b');
cy.get('.euiDataGridColumnSelector__item').eq(1).should('have.text', 'c');
cy.get('.euiDataGridColumnSelector__item').eq(2).should('have.text', 'd');
cy.get('.euiDataGridColumnSelector__item').eq(3).should('have.text', 'a');
});
});
});

function getGridData() {
Expand Down