Skip to content

Commit

Permalink
[EuiDataGrid] Various row manager fixes (#7301)
Browse files Browse the repository at this point in the history
  • Loading branch information
cee-chen authored Oct 23, 2023
1 parent de10c65 commit 7e0f805
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 9 deletions.
32 changes: 32 additions & 0 deletions src/components/datagrid/body/data_grid_row_manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,24 @@ describe('row manager', () => {
/>
`);
});

it("updates the row's visible row index and striping on sort", () => {
const row = rowManager.getRow({
rowIndex: 0,
visibleRowIndex: 3,
top: '100px',
height: 200,
});
expect(row).toMatchInlineSnapshot(`
<div
class="euiDataGridRow euiDataGridRow--striped"
data-grid-row-index="0"
data-grid-visible-row-index="3"
role="row"
style="position: absolute; left: 0px; right: 0px; top: 100px; height: 200px;"
/>
`);
});
});

describe("when the row's child cells are all removed", () => {
Expand Down Expand Up @@ -132,6 +150,12 @@ describe('row manager', () => {
expect(row0.classList.contains('world')).toBe(true);
});

it('allows passing multiple classes', () => {
rerender({ ...mockArgs, rowClasses: { 0: 'hello world' } });
expect(getRow(0).classList.contains('hello')).toBe(true);
expect(getRow(0).classList.contains('world')).toBe(true);
});

it('adds/removes row classes correctly when gridStyle.rowClasses updates', () => {
rerender({ ...mockArgs, rowClasses: { 1: 'test' } });
const row0 = getRow(0);
Expand All @@ -141,5 +165,13 @@ describe('row manager', () => {
expect(row0.classList.contains('world')).toBe(false);
expect(row1.classList.contains('test')).toBe(true);
});

it('correctly preserves EUI classes when adding/removing classes dynamically', () => {
rerender({ ...mockArgs, rowClasses: undefined });

expect(getRow(0).classList.value).toEqual(
'euiDataGridRow euiDataGridRow--striped'
);
});
});
});
32 changes: 23 additions & 9 deletions src/components/datagrid/body/data_grid_row_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
* Side Public License, v 1.
*/

import { useRef, useCallback, useEffect, RefObject } from 'react';
import { useRef, useCallback, RefObject } from 'react';
import { useUpdateEffect } from '../../../services';

import { EuiDataGridRowManager, EuiDataGridStyle } from '../data_grid_types';

export const useRowManager = ({
Expand All @@ -25,14 +27,11 @@ export const useRowManager = ({
if (rowElement == null) {
rowElement = document.createElement('div');
rowElement.setAttribute('role', 'row');
rowElement.dataset.gridRowIndex = String(rowIndex); // Row index from data, affected by sorting/pagination
rowElement.dataset.gridVisibleRowIndex = String(visibleRowIndex); // Affected by sorting/pagination
rowElement.dataset.gridRowIndex = String(rowIndex); // Row index from data, not affected by sorting/pagination
rowElement.classList.add('euiDataGridRow');
if (rowClasses?.[rowIndex]) {
rowElement.classList.add(rowClasses[rowIndex]);
rowElement.classList.add(...rowClasses[rowIndex].split(' '));
}
const isOddRow = visibleRowIndex % 2 !== 0;
if (isOddRow) rowElement.classList.add('euiDataGridRow--striped');
rowElement.style.position = 'absolute';
rowElement.style.left = '0';
rowElement.style.right = '0';
Expand All @@ -58,6 +57,17 @@ export const useRowManager = ({
observer.observe(rowElement, { childList: true });
}

// Ensure the row's visible row index & striping update correctly on sort & pagination
if (rowElement.dataset.gridVisibleRowIndex !== String(visibleRowIndex)) {
rowElement.dataset.gridVisibleRowIndex = String(visibleRowIndex);
const isOddRow = visibleRowIndex % 2 !== 0;
if (isOddRow) {
rowElement.classList.add('euiDataGridRow--striped');
} else {
rowElement.classList.remove('euiDataGridRow--striped');
}
}

// Ensure that the row's dimensions are always correct by having each cell update position styles
rowElement.style.top = top;
rowElement.style.height = `${height}px`;
Expand All @@ -68,13 +78,17 @@ export const useRowManager = ({
);

// Update row classes dynamically whenever a new prop is passed in
useEffect(() => {
useUpdateEffect(() => {
if (rowClasses) {
rowIdToElements.current.forEach((rowElement, rowIndex) => {
const euiClasses = Array.from(rowElement.classList)
.filter((className) => className.startsWith('euiDataGridRow'))
.join(' ');

if (rowClasses[rowIndex]) {
rowElement.classList.value = `euiDataGridRow ${rowClasses[rowIndex]}`;
rowElement.classList.value = `${euiClasses} ${rowClasses[rowIndex]}`;
} else {
rowElement.classList.value = 'euiDataGridRow'; // Clear any added classes
rowElement.classList.value = euiClasses; // Clear any added classes
}
});
}
Expand Down
5 changes: 5 additions & 0 deletions upcoming_changelogs/7301.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
**Bug fixes**

- Fixed `EuiDataGrid`s with `gridStyle.stripes` sometimes showing buggy row striping after being sorted
- Fixed `EuiDataGrid`'s `gridStyle.rowClasses` API to not conflict with `gridStyle.stripes` if dynamically updated
- Fixed `EuiDataGrid`'s `gridStyle.rowClasses` API to support multiple space-separated classes

0 comments on commit 7e0f805

Please sign in to comment.