Skip to content

Commit fc51609

Browse files
committed
Create a CellProps configuration component
1 parent f58e3a5 commit fc51609

File tree

5 files changed

+117
-78
lines changed

5 files changed

+117
-78
lines changed

src-docs/src/views/datagrid/datagrid.js

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React, {
22
Fragment,
33
useCallback,
4-
useEffect,
54
useMemo,
65
useState,
76
createContext,
@@ -366,33 +365,40 @@ export default () => {
366365
); // initialize to the full set of columns
367366

368367
const renderCellValue = useMemo(() => {
369-
return ({ rowIndex, columnId, setCellProps }) => {
368+
return ({ rowIndex, columnId, CellProps }) => {
370369
const data = useContext(DataContext);
371-
useEffect(() => {
372-
if (columnId === 'amount') {
373-
if (data.hasOwnProperty(rowIndex)) {
374-
const numeric = parseFloat(
375-
data[rowIndex][columnId].match(/\d+\.\d+/)[0],
376-
10
377-
);
378-
setCellProps({
379-
style: {
380-
backgroundColor: `rgba(0, 255, 0, ${numeric * 0.0002})`,
381-
},
382-
});
383-
}
384-
}
385-
}, [rowIndex, columnId, setCellProps, data]);
386370

387371
function getFormatted() {
388372
return data[rowIndex][columnId].formatted
389373
? data[rowIndex][columnId].formatted
390374
: data[rowIndex][columnId];
391375
}
392376

393-
return data.hasOwnProperty(rowIndex)
377+
const content = data.hasOwnProperty(rowIndex)
394378
? getFormatted(rowIndex, columnId)
395379
: null;
380+
381+
// Apply custom background color to cells in the `amount` columns
382+
let cellProps = undefined;
383+
if (columnId === 'amount') {
384+
const numeric = parseFloat(content.match(/\d+\.\d+/)[0], 10);
385+
cellProps = (
386+
<CellProps
387+
props={{
388+
style: {
389+
backgroundColor: `rgba(0, 255, 0, ${numeric * 0.0002})`,
390+
},
391+
}}
392+
/>
393+
);
394+
}
395+
396+
return (
397+
<>
398+
{content}
399+
{cellProps}
400+
</>
401+
);
396402
};
397403
}, []);
398404

src/components/datagrid/body/__snapshots__/data_grid_cell.test.tsx.snap

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,39 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`EuiDataGridCell componentDidUpdate handles the cell popover by forwarding the cell's DOM node and contents to the parent popover context 1`] = `
4+
Array [
5+
<div
6+
data-test-subj="popover-test"
7+
>
8+
<div>
9+
<button
10+
data-datagrid-interactable="true"
11+
>
12+
hello
13+
</button>
14+
<button
15+
data-datagrid-interactable="true"
16+
>
17+
world
18+
</button>
19+
</div>
20+
</div>,
21+
<div
22+
class="euiPopoverFooter"
23+
>
24+
<div
25+
class="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--directionRow euiFlexGroup--responsive"
26+
>
27+
<div
28+
class="euiFlexItem"
29+
>
30+
<button />
31+
</div>
32+
</div>
33+
</div>,
34+
]
35+
`;
36+
337
exports[`EuiDataGridCell renders 1`] = `
438
<EuiDataGridCell
539
colIndex={0}
@@ -83,6 +117,7 @@ exports[`EuiDataGridCell renders 1`] = `
83117
className="euiDataGridRowCell__expandContent"
84118
>
85119
<Memo()
120+
CellProps={[Function]}
86121
colIndex={0}
87122
columnId="someColumn"
88123
isDefinedHeight={false}
@@ -131,6 +166,7 @@ exports[`EuiDataGridCell renders 1`] = `
131166
style={Object {}}
132167
>
133168
<renderCellValue
169+
CellProps={[Function]}
134170
columnId="someColumn"
135171
data-test-subj="cell-content"
136172
isDetails={false}
@@ -167,37 +203,3 @@ exports[`EuiDataGridCell renders 1`] = `
167203
</div>
168204
</EuiDataGridCell>
169205
`;
170-
171-
exports[`EuiDataGridCell componentDidUpdate handles the cell popover by forwarding the cell's DOM node and contents to the parent popover context 1`] = `
172-
Array [
173-
<div
174-
data-test-subj="popover-test"
175-
>
176-
<div>
177-
<button
178-
data-datagrid-interactable="true"
179-
>
180-
hello
181-
</button>
182-
<button
183-
data-datagrid-interactable="true"
184-
>
185-
world
186-
</button>
187-
</div>
188-
</div>,
189-
<div
190-
class="euiPopoverFooter"
191-
>
192-
<div
193-
class="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--directionRow euiFlexGroup--responsive"
194-
>
195-
<div
196-
class="euiFlexItem"
197-
>
198-
<button />
199-
</div>
200-
</div>
201-
</div>,
202-
]
203-
`;

src/components/datagrid/body/data_grid_cell.tsx

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import classNames from 'classnames';
1010
import React, {
1111
Component,
12+
createContext,
1213
createRef,
1314
FocusEvent,
1415
FunctionComponent,
@@ -17,6 +18,8 @@ import React, {
1718
KeyboardEvent,
1819
memo,
1920
MutableRefObject,
21+
useContext,
22+
useEffect,
2023
} from 'react';
2124
import { createPortal } from 'react-dom';
2225
import tabbable from 'tabbable';
@@ -41,6 +44,7 @@ import { IS_JEST_ENVIRONMENT } from '../../../test';
4144
const EuiDataGridCellContent: FunctionComponent<
4245
EuiDataGridCellValueProps & {
4346
setCellProps: EuiDataGridCellValueElementProps['setCellProps'];
47+
CellProps: typeof CellProps;
4448
setCellContentsRef: EuiDataGridCell['setCellContentsRef'];
4549
isExpanded: boolean;
4650
isDefinedHeight: boolean;
@@ -99,6 +103,22 @@ const EuiDataGridCellContent: FunctionComponent<
99103
}
100104
);
101105

106+
const CellPropsContext = createContext<{
107+
setCellProps: (props: HTMLAttributes<HTMLDivElement>) => void;
108+
}>({
109+
setCellProps: () => {},
110+
});
111+
112+
export const CellProps: FunctionComponent<{
113+
props: HTMLAttributes<HTMLDivElement>;
114+
}> = ({ props }) => {
115+
const { setCellProps } = useContext(CellPropsContext);
116+
useEffect(() => {
117+
setCellProps(props);
118+
}, [setCellProps, props]);
119+
return null;
120+
};
121+
102122
export class EuiDataGridCell extends Component<
103123
EuiDataGridCellProps,
104124
EuiDataGridCellState
@@ -469,6 +489,7 @@ export class EuiDataGridCell extends Component<
469489
isExpandable={true}
470490
isExpanded={true}
471491
setCellProps={this.setCellProps}
492+
CellProps={CellProps}
472493
isDetails={true}
473494
/>
474495
</PopoverContent>
@@ -599,6 +620,7 @@ export class EuiDataGridCell extends Component<
599620
const cellContentProps = {
600621
...rest,
601622
setCellProps: this.setCellProps,
623+
CellProps,
602624
column,
603625
columnType: columnType,
604626
isExpandable,
@@ -668,32 +690,34 @@ export class EuiDataGridCell extends Component<
668690
}
669691

670692
const content = (
671-
<div
672-
role="gridcell"
673-
tabIndex={
674-
this.state.isFocused && !this.state.disableCellTabIndex ? 0 : -1
675-
}
676-
ref={this.cellRef}
677-
{...cellProps}
678-
data-test-subj="dataGridRowCell"
679-
// Data attributes to help target specific cells by either data or current cell location
680-
data-gridcell-column-id={this.props.columnId} // Static column ID name, not affected by column order
681-
data-gridcell-column-index={this.props.colIndex} // Affected by column reordering
682-
data-gridcell-row-index={this.props.rowIndex} // Index from data, not affected by sorting or pagination
683-
data-gridcell-visible-row-index={this.props.visibleRowIndex} // Affected by sorting & pagination
684-
data-gridcell-id={`${this.props.colIndex},${this.props.rowIndex}`} // TODO: Deprecate in favor of the above 4 data attrs
685-
onKeyDown={handleCellKeyDown}
686-
onFocus={this.onFocus}
687-
onMouseEnter={() => {
688-
this.setState({ enableInteractions: true });
689-
}}
690-
onMouseLeave={() => {
691-
this.setState({ enableInteractions: false });
692-
}}
693-
onBlur={this.onBlur}
694-
>
695-
{innerContent}
696-
</div>
693+
<CellPropsContext.Provider value={{ setCellProps: this.setCellProps }}>
694+
<div
695+
role="gridcell"
696+
tabIndex={
697+
this.state.isFocused && !this.state.disableCellTabIndex ? 0 : -1
698+
}
699+
ref={this.cellRef}
700+
{...cellProps}
701+
data-test-subj="dataGridRowCell"
702+
// Data attributes to help target specific cells by either data or current cell location
703+
data-gridcell-column-id={this.props.columnId} // Static column ID name, not affected by column order
704+
data-gridcell-column-index={this.props.colIndex} // Affected by column reordering
705+
data-gridcell-row-index={this.props.rowIndex} // Index from data, not affected by sorting or pagination
706+
data-gridcell-visible-row-index={this.props.visibleRowIndex} // Affected by sorting & pagination
707+
data-gridcell-id={`${this.props.colIndex},${this.props.rowIndex}`} // TODO: Deprecate in favor of the above 4 data attrs
708+
onKeyDown={handleCellKeyDown}
709+
onFocus={this.onFocus}
710+
onMouseEnter={() => {
711+
this.setState({ enableInteractions: true });
712+
}}
713+
onMouseLeave={() => {
714+
this.setState({ enableInteractions: false });
715+
}}
716+
onBlur={this.onBlur}
717+
>
718+
{innerContent}
719+
</div>
720+
</CellPropsContext.Provider>
697721
);
698722

699723
return rowManager && !IS_JEST_ENVIRONMENT

src/components/datagrid/data_grid_types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
Dispatch,
1919
SetStateAction,
2020
MutableRefObject,
21+
FunctionComponent,
2122
} from 'react';
2223
import {
2324
VariableSizeGridProps,
@@ -389,6 +390,10 @@ export interface EuiDataGridCellValueElementProps {
389390
* it's best to wrap calls to `setCellProps` in a `useEffect` hook
390391
*/
391392
setCellProps: (props: CommonProps & HTMLAttributes<HTMLDivElement>) => void;
393+
/**
394+
* React component that can be used to specific custom props & attributes on the cell's wrapping `div` element
395+
*/
396+
CellProps: FunctionComponent<{ props: HTMLAttributes<HTMLDivElement> }>;
392397
/**
393398
* whether or not the cell is expandable, comes from the #EuiDataGridColumn `isExpandable` which defaults to `true`
394399
*/

src/components/datagrid/utils/in_memory.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
EuiDataGridInMemoryRendererProps,
2525
EuiDataGridCellValueElementProps,
2626
} from '../data_grid_types';
27+
import { CellProps } from '../body/data_grid_cell';
2728

2829
/**
2930
* inMemory values hook
@@ -124,6 +125,7 @@ export const EuiDataGridInMemoryRenderer: FunctionComponent<EuiDataGridInMemoryR
124125
rowIndex={i}
125126
columnId={column.id}
126127
setCellProps={noop}
128+
CellProps={CellProps}
127129
isExpandable={isExpandable}
128130
isExpanded={false}
129131
isDetails={false}

0 commit comments

Comments
 (0)