diff --git a/src-docs/src/views/datagrid/datagrid.js b/src-docs/src/views/datagrid/datagrid.js
index 070ac54aa45..fca7e084203 100644
--- a/src-docs/src/views/datagrid/datagrid.js
+++ b/src-docs/src/views/datagrid/datagrid.js
@@ -1,12 +1,21 @@
-import React, { Component, Fragment, useEffect } from 'react';
+import React, {
+ Fragment,
+ useCallback,
+ useEffect,
+ useMemo,
+ useState,
+} from 'react';
import { fake } from 'faker';
import {
+ EuiButton,
EuiDataGrid,
EuiButtonIcon,
EuiLink,
+ EuiPopover,
} from '../../../../src/components/';
import { iconTypes } from '../../../../src-docs/src/views/icon/icons';
+import { EuiRadioGroup } from '../../../../src/components/form/radio';
const columns = [
{
@@ -38,10 +47,10 @@ const columns = [
},
];
-const data = [];
+const raw_data = [];
-for (let i = 1; i < 100; i++) {
- data.push({
+for (let i = 1; i < 1000; i++) {
+ raw_data.push({
name: fake('{{name.lastName}}, {{name.firstName}} {{name.suffix}}'),
email: {fake('{{internet.email}}')},
location: (
@@ -72,22 +81,39 @@ for (let i = 1; i < 100; i++) {
});
}
-export default class DataGridContainer extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- sortingColumns: [],
- data,
- pagination: {
- pageIndex: 0,
- pageSize: 50,
- },
- };
- }
+export default () => {
+ const [isPopoverOpen, setIsPopoverOpen] = useState(false);
+
+ // ** Pagination config
+ const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 25 });
+ const onChangeItemsPerPage = useCallback(
+ pageSize => setPagination(pagination => ({ ...pagination, pageSize })),
+ [setPagination]
+ );
+ const onChangePage = useCallback(
+ pageIndex => setPagination(pagination => ({ ...pagination, pageIndex })),
+ [setPagination]
+ );
+
+ // ** Sorting config
+ const [sortingColumns, setSortingColumns] = useState([]);
+ const onSort = useCallback(
+ sortingColumns => {
+ setSortingColumns(sortingColumns);
+ },
+ [setSortingColumns]
+ );
- setSorting = sortingColumns => {
- const sortedData = [...data].sort((a, b) => {
+ const [inMemoryLevel, setInMemoryLevel] = useState('');
+
+ // Sort data
+ let data = useMemo(() => {
+ // the grid itself is responsible for sorting if inMemory is `sorting`
+ if (inMemoryLevel === 'sorting') {
+ return raw_data;
+ }
+
+ return [...raw_data].sort((a, b) => {
for (let i = 0; i < sortingColumns.length; i++) {
const column = sortingColumns[i];
const aValue = a[column.id];
@@ -99,58 +125,117 @@ export default class DataGridContainer extends Component {
return 0;
});
- this.setState({ sortingColumns, data: sortedData });
- };
-
- setPageIndex = pageIndex =>
- this.setState(({ pagination }) => ({
- pagination: { ...pagination, pageIndex },
- }));
-
- setPageSize = pageSize =>
- this.setState(({ pagination }) => ({
- pagination: { ...pagination, pageSize },
- }));
-
- dummyIcon = () => (
-
- );
+ }, [raw_data, sortingColumns, inMemoryLevel]);
+
+ // Pagination
+ data = useMemo(() => {
+ // the grid itself is responsible for sorting if inMemory is sorting or pagination
+ if (inMemoryLevel === 'sorting' || inMemoryLevel === 'pagination') {
+ return data;
+ }
+
+ const rowStart = pagination.pageIndex * pagination.pageSize;
+ const rowEnd = Math.min(rowStart + pagination.pageSize, data.length);
+ return data.slice(rowStart, rowEnd);
+ }, [data, pagination, inMemoryLevel]);
+
+ const renderCellValue = useMemo(() => {
+ return ({ rowIndex, columnId, setCellProps }) => {
+ let adjustedRowIndex = rowIndex;
- render() {
- const { data, pagination, sortingColumns } = this.state;
+ // If we are doing the pagination (instead of leaving that to the grid)
+ // then the row index must be adjusted as `data` has already been pruned to the page size
+ if (inMemoryLevel !== 'sorting' && inMemoryLevel !== 'pagination') {
+ adjustedRowIndex =
+ rowIndex - pagination.pageIndex * pagination.pageSize;
+ }
+
+ useEffect(() => {
+ if (columnId === 'amount') {
+ if (data.hasOwnProperty(adjustedRowIndex)) {
+ const numeric = parseFloat(
+ data[adjustedRowIndex][columnId].match(/\d+\.\d+/)[0],
+ 10
+ );
+ setCellProps({
+ style: {
+ backgroundColor: `rgba(0, ${(numeric / 1000) * 255}, 0, 0.2)`,
+ },
+ });
+ }
+ }
+ }, [adjustedRowIndex, columnId, setCellProps]);
+
+ return data.hasOwnProperty(adjustedRowIndex)
+ ? data[adjustedRowIndex][columnId]
+ : null;
+ };
+ }, [data, inMemoryLevel]);
+
+ const inMemoryProps = {};
+ if (inMemoryLevel !== '') {
+ inMemoryProps.inMemory = {
+ level: inMemoryLevel,
+ skipColumns: ['actions'],
+ };
+ }
+
+ return (
+
+ setIsPopoverOpen(state => !state)}>
+ inMemory options
+
+ }
+ closePopover={() => setIsPopoverOpen(false)}>
+ {
+ setInMemoryLevel(value === '' ? undefined : value);
+ setIsPopoverOpen(false);
+ }}
+ />
+
- return (
{
- useEffect(() => {
- if (columnId === 'amount') {
- const numeric = parseFloat(
- data[rowIndex][columnId].match(/\d+\.\d+/)[0],
- 10
- );
- setCellProps({
- style: {
- backgroundColor: `rgba(0, ${(numeric / 1000) * 255}, 0, 0.2)`,
- },
- });
- }
- }, [rowIndex, columnId, setCellProps]);
- return data[rowIndex][columnId];
- }}
- sorting={{ columns: sortingColumns, onSort: this.setSorting }}
+ rowCount={raw_data.length}
+ renderCellValue={renderCellValue}
+ {...inMemoryProps}
+ sorting={{ columns: sortingColumns, onSort }}
pagination={{
...pagination,
- pageSizeOptions: [5, 10, 25],
- onChangeItemsPerPage: this.setPageSize,
- onChangePage: this.setPageIndex,
+ pageSizeOptions: [10, 25, 50, 100],
+ onChangeItemsPerPage: onChangeItemsPerPage,
+ onChangePage: onChangePage,
}}
/>
- );
- }
-}
+
+ );
+};
diff --git a/src-docs/src/views/datagrid/in_memory.js b/src-docs/src/views/datagrid/in_memory.js
index 6b68a9943e7..67d9d011290 100644
--- a/src-docs/src/views/datagrid/in_memory.js
+++ b/src-docs/src/views/datagrid/in_memory.js
@@ -91,7 +91,7 @@ export default class InMemoryDataGrid extends Component {
const value = data[rowIndex][columnId];
return value;
}}
- inMemory="sorting"
+ inMemory={{ level: 'sorting' }}
sorting={{ columns: sortingColumns, onSort: this.setSorting }}
pagination={{
...pagination,
diff --git a/src-docs/src/views/datagrid/schema.js b/src-docs/src/views/datagrid/schema.js
index 200170927c4..f1feccf3629 100644
--- a/src-docs/src/views/datagrid/schema.js
+++ b/src-docs/src/views/datagrid/schema.js
@@ -74,7 +74,22 @@ export default class InMemoryDataGrid extends Component {
};
}
- setSorting = sortingColumns => this.setState({ sortingColumns });
+ setSorting = sortingColumns => {
+ const data = [...this.state.data].sort((a, b) => {
+ for (let i = 0; i < sortingColumns.length; i++) {
+ const column = sortingColumns[i];
+ const aValue = a[column.id];
+ const bValue = b[column.id];
+
+ if (aValue < bValue) return column.direction === 'asc' ? -1 : 1;
+ if (aValue > bValue) return column.direction === 'asc' ? 1 : -1;
+ }
+
+ return 0;
+ });
+
+ this.setState({ data, sortingColumns });
+ };
setPageIndex = pageIndex =>
this.setState(({ pagination }) => ({
diff --git a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap
index 3dd2294ec54..a8fcfe29e0e 100644
--- a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap
+++ b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap
@@ -319,33 +319,14 @@ Array [
role="gridcell"
tabindex="0"
>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/components/datagrid/column_selector.tsx b/src/components/datagrid/column_selector.tsx
index d5486b08ca0..cda4989c528 100644
--- a/src/components/datagrid/column_selector.tsx
+++ b/src/components/datagrid/column_selector.tsx
@@ -1,9 +1,4 @@
-import React, {
- Fragment,
- FunctionComponent,
- useState,
- ReactChild,
-} from 'react';
+import React, { Fragment, useState, ReactChild, ReactElement } from 'react';
import classNames from 'classnames';
import { EuiDataGridColumn } from './data_grid_types';
// @ts-ignore-next-line
@@ -24,7 +19,7 @@ import { EuiIcon } from '../icon';
export const useColumnSelector = (
availableColumns: EuiDataGridColumn[]
-): [FunctionComponent
, EuiDataGridColumn[]] => {
+): [ReactElement, EuiDataGridColumn[]] => {
const [sortedColumns, setSortedColumns] = useState(availableColumns);
const [visibleColumns, setVisibleColumns] = useState(availableColumns);
@@ -59,7 +54,7 @@ export const useColumnSelector = (
'euiDataGrid__controlBtn--active': numberOfHiddenFields > 0,
});
- const ColumnSelector = () => (
+ const columnSelector = (
);
- return [ColumnSelector, visibleColumns];
+ return [columnSelector, visibleColumns];
};
diff --git a/src/components/datagrid/data_grid.test.tsx b/src/components/datagrid/data_grid.test.tsx
index 70646e046a5..59b57f921a3 100644
--- a/src/components/datagrid/data_grid.test.tsx
+++ b/src/components/datagrid/data_grid.test.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useEffect, useState } from 'react';
import { mount, ReactWrapper, render } from 'enzyme';
import { EuiDataGrid } from './';
import {
@@ -315,11 +315,13 @@ describe('EuiDataGrid', () => {
columns={[{ id: 'A' }, { id: 'B' }]}
rowCount={2}
renderCellValue={({ rowIndex, columnId, setCellProps }) => {
- setCellProps({
- className: 'customClass',
- 'data-test-subj': `cell-${rowIndex}-${columnId}`,
- style: { color: columnId === 'A' ? 'red' : 'blue' },
- });
+ useEffect(() => {
+ setCellProps({
+ className: 'customClass',
+ 'data-test-subj': `cell-${rowIndex}-${columnId}`,
+ style: { color: columnId === 'A' ? 'red' : 'blue' },
+ });
+ }, []);
return `${rowIndex}, ${columnId}`;
}}
@@ -418,7 +420,7 @@ Array [
{
if (columnId === 'A') {
@@ -452,7 +454,7 @@ Array [
columnId === 'A' ? 5.5 : 'true'
@@ -487,7 +489,7 @@ Array [
({ id }))}
- inMemory="pagination"
+ inMemory={{ level: 'pagination' }}
rowCount={1}
renderCellValue={({ columnId }) => values[columnId]}
/>
@@ -528,7 +530,7 @@ Array [
},
},
]}
- inMemory="pagination"
+ inMemory={{ level: 'pagination' }}
rowCount={1}
renderCellValue={({ columnId }) => values[columnId]}
/>
@@ -937,7 +939,7 @@ Array [
// render A 0->4 and B 9->5
columnId === 'A' ? rowIndex : 9 - rowIndex
}
- inMemory="sorting"
+ inMemory={{ level: 'sorting' }}
sorting={{
columns: [{ id: 'A', direction: 'desc' }],
onSort: () => {},
@@ -965,7 +967,7 @@ Array [
// render A as 0, 1, 0, 1, 0 and B as 9->5
columnId === 'A' ? rowIndex % 2 : 9 - rowIndex
}
- inMemory="sorting"
+ inMemory={{ level: 'sorting' }}
sorting={{
columns: [
{ id: 'A', direction: 'desc' },
@@ -1001,7 +1003,7 @@ Array [
// render A as 0, 1, 0, 1, 0 and B as 9->5
columnId === 'A' ? rowIndex % 2 : 9 - rowIndex
}
- inMemory="sorting"
+ inMemory={{ level: 'sorting' }}
sorting={{
columns: [],
onSort,
diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx
index e7ead4bfea6..6b685472eb0 100644
--- a/src/components/datagrid/data_grid.tsx
+++ b/src/components/datagrid/data_grid.tsx
@@ -270,7 +270,10 @@ function useOnResize(
);
}
-function useInMemoryValues(): [
+function useInMemoryValues(
+ inMemory: EuiDataGridInMemory | undefined,
+ rowCount: number
+): [
EuiDataGridInMemoryValues,
(rowIndex: number, column: EuiDataGridColumn, value: string) => void
] {
@@ -281,15 +284,21 @@ function useInMemoryValues(): [
const onCellRender = useCallback(
(rowIndex, column, value) => {
setInMemoryValues(inMemoryValues => {
- const nextInMemoryVaues = { ...inMemoryValues };
- nextInMemoryVaues[rowIndex] = nextInMemoryVaues[rowIndex] || {};
- nextInMemoryVaues[rowIndex][column.id] = value;
- return nextInMemoryVaues;
+ const nextInMemoryValues = { ...inMemoryValues };
+ nextInMemoryValues[rowIndex] = nextInMemoryValues[rowIndex] || {};
+ nextInMemoryValues[rowIndex][column.id] = value;
+ return nextInMemoryValues;
});
},
- [inMemoryValues, setInMemoryValues]
+ [setInMemoryValues]
);
+ // if `inMemory.level` or `rowCount` changes reset the values
+ const inMemoryLevel = inMemory && inMemory.level;
+ useEffect(() => {
+ setInMemoryValues({});
+ }, [inMemoryLevel, rowCount]);
+
return [inMemoryValues, onCellRender];
}
@@ -324,27 +333,27 @@ function createKeyDownHandler(
if (isGridNavigationEnabled) {
switch (keyCode) {
case keyCodes.DOWN:
- if (y < rowCount) {
- event.preventDefault();
+ event.preventDefault();
+ if (y < rowCount - 1) {
setFocusedCell([x, y + 1]);
}
break;
case keyCodes.LEFT:
+ event.preventDefault();
if (x > 0) {
- event.preventDefault();
setFocusedCell([x - 1, y]);
}
break;
case keyCodes.UP:
+ event.preventDefault();
// TODO sort out when a user can arrow up into the column headers
if (y > 0) {
- event.preventDefault();
setFocusedCell([x, y - 1]);
}
break;
case keyCodes.RIGHT:
+ event.preventDefault();
if (x < colCount) {
- event.preventDefault();
setFocusedCell([x + 1, y]);
}
break;
@@ -389,15 +398,15 @@ export const EuiDataGrid: FunctionComponent = props => {
gridStyle,
pagination,
sorting,
- inMemory = false,
+ inMemory,
...rest
} = props;
// apply style props on top of defaults
const gridStyleWithDefaults = { ...startingStyles, ...gridStyle };
- const [ColumnSelector, visibleColumns] = useColumnSelector(columns);
- const [StyleSelector, gridStyles] = useStyleSelector(gridStyleWithDefaults);
+ const [columnSelector, visibleColumns] = useColumnSelector(columns);
+ const [styleSelector, gridStyles] = useStyleSelector(gridStyleWithDefaults);
// compute the default column width from the container's clientWidth and count of visible columns
const defaultColumnWidth = useDefaultColumnWidth(
@@ -429,20 +438,20 @@ export const EuiDataGrid: FunctionComponent = props => {
className
);
- const [inMemoryValues, onCellRender] = useInMemoryValues();
+ const [inMemoryValues, onCellRender] = useInMemoryValues(inMemory, rowCount);
const detectedSchema = useDetectSchema(
inMemoryValues,
schemaDetectors,
- inMemory !== false
+ inMemory != null
);
const mergedSchema = getMergedSchema(detectedSchema, columns);
// These grid controls will only show when there is room. Check the resize observer callback
const gridControls = (
-
-
+ {columnSelector}
+ {styleSelector}
);
@@ -513,9 +522,16 @@ export const EuiDataGrid: FunctionComponent = props => {
{inMemory ? (
) : null}
diff --git a/src/components/datagrid/data_grid_body.tsx b/src/components/datagrid/data_grid_body.tsx
index 6d5a1c04af0..4a225733129 100644
--- a/src/components/datagrid/data_grid_body.tsx
+++ b/src/components/datagrid/data_grid_body.tsx
@@ -28,7 +28,7 @@ interface EuiDataGridBodyProps {
onCellFocus: EuiDataGridDataRowProps['onCellFocus'];
rowCount: number;
renderCellValue: EuiDataGridCellProps['renderCellValue'];
- inMemory: EuiDataGridInMemory;
+ inMemory?: EuiDataGridInMemory;
inMemoryValues: EuiDataGridInMemoryValues;
isGridNavigationEnabled: EuiDataGridCellProps['isGridNavigationEnabled'];
interactiveCellId: EuiDataGridCellProps['interactiveCellId'];
@@ -74,7 +74,8 @@ export const EuiDataGridBody: FunctionComponent<
const rowMap: { [key: number]: number } = {};
if (
- inMemory === 'sorting' &&
+ inMemory &&
+ inMemory.level === 'sorting' &&
sorting != null &&
sorting.columns.length > 0
) {
@@ -123,9 +124,14 @@ export const EuiDataGridBody: FunctionComponent<
break;
}
}
+
+ // map the row into the visible rows
+ if (pagination) {
+ reverseMappedIndex -= pagination.pageIndex * pagination.pageSize;
+ }
onCellFocus([colIndex, reverseMappedIndex]);
},
- [onCellFocus, rowMap]
+ [onCellFocus, rowMap, pagination]
);
const rows = useMemo(() => {
diff --git a/src/components/datagrid/data_grid_cell.tsx b/src/components/datagrid/data_grid_cell.tsx
index f15e3e07029..312c9bf7009 100644
--- a/src/components/datagrid/data_grid_cell.tsx
+++ b/src/components/datagrid/data_grid_cell.tsx
@@ -8,8 +8,6 @@ import React, {
HTMLAttributes,
} from 'react';
import classnames from 'classnames';
-// @ts-ignore
-import { EuiFocusTrap } from '../focus_trap';
import { CommonProps, Omit } from '../common';
import { getTabbables, CELL_CONTENTS_ATTR } from './utils';
import { EuiMutationObserver } from '../observer/mutation_observer';
@@ -41,7 +39,11 @@ interface EuiDataGridCellState {
type EuiDataGridCellValueProps = Omit<
EuiDataGridCellProps,
- 'width' | 'isFocusable' | 'isGridNavigationEnabled' | 'interactiveCellId'
+ | 'width'
+ | 'isFocusable'
+ | 'isGridNavigationEnabled'
+ | 'interactiveCellId'
+ | 'onCellFocus'
>;
const EuiDataGridCellContent: FunctionComponent<
@@ -167,7 +169,10 @@ export class EuiDataGridCell extends Component<
}
}
- shouldComponentUpdate(nextProps: EuiDataGridCellProps) {
+ shouldComponentUpdate(
+ nextProps: EuiDataGridCellProps,
+ nextState: EuiDataGridCellState
+ ) {
if (nextProps.rowIndex !== this.props.rowIndex) return true;
if (nextProps.colIndex !== this.props.colIndex) return true;
if (nextProps.columnId !== this.props.columnId) return true;
@@ -181,6 +186,9 @@ export class EuiDataGridCell extends Component<
return true;
if (nextProps.interactiveCellId !== this.props.interactiveCellId)
return true;
+
+ if (nextState.cellProps !== this.state.cellProps) return true;
+
return false;
}
@@ -195,9 +203,10 @@ export class EuiDataGridCell extends Component<
isGridNavigationEnabled,
interactiveCellId,
columnType,
+ onCellFocus,
...rest
} = this.props;
- const { colIndex, rowIndex, onCellFocus } = rest;
+ const { colIndex, rowIndex } = rest;
const isInteractive = this.isInteractiveCell();
const isInteractiveCell = {
[CELL_CONTENTS_ATTR]: isInteractive,
@@ -232,32 +241,30 @@ export class EuiDataGridCell extends Component<
{...cellProps}
data-test-subj="dataGridRowCell"
onFocus={() => onCellFocus([colIndex, rowIndex])}>
-
- {
- this.updateFocus();
- this.setTabbablesTabIndex();
- }}
- observerOptions={{
- childList: true,
- subtree: true,
- }}>
- {ref => (
-
-
-
-
+
{
+ this.updateFocus();
+ this.setTabbablesTabIndex();
+ }}
+ observerOptions={{
+ childList: true,
+ subtree: true,
+ }}>
+ {ref => (
+
+ )}
+
);
}
diff --git a/src/components/datagrid/data_grid_inmemory_renderer.tsx b/src/components/datagrid/data_grid_inmemory_renderer.tsx
index 64b8cf1e400..fa320900585 100644
--- a/src/components/datagrid/data_grid_inmemory_renderer.tsx
+++ b/src/components/datagrid/data_grid_inmemory_renderer.tsx
@@ -6,12 +6,12 @@ import React, {
useMemo,
useState,
} from 'react';
-import { createPortal } from 'react-dom';
+import { createPortal, unstable_batchedUpdates } from 'react-dom';
import { CellValueElementProps, EuiDataGridCellProps } from './data_grid_cell';
-import { EuiDataGridColumn } from './data_grid_types';
-import { EuiInnerText } from '../inner_text';
+import { EuiDataGridColumn, EuiDataGridInMemory } from './data_grid_types';
interface EuiDataGridInMemoryRendererProps {
+ inMemory: EuiDataGridInMemory;
columns: EuiDataGridColumn[];
rowCount: number;
renderCellValue: EuiDataGridCellProps['renderCellValue'];
@@ -24,49 +24,113 @@ interface EuiDataGridInMemoryRendererProps {
function noop() {}
+const _queue: Function[] = [];
+
+function processQueue() {
+ // the queued functions trigger react setStates which, if unbatched,
+ // each cause a full update->render->dom pass _per function_
+ // instead, tell React to wait until all updates are finished before re-rendering
+ unstable_batchedUpdates(() => {
+ for (let i = 0; i < _queue.length; i++) {
+ _queue[i]();
+ }
+ _queue.length = 0;
+ });
+}
+
+function enqueue(fn: Function) {
+ if (_queue.length === 0) {
+ setTimeout(processQueue);
+ }
+ _queue.push(fn);
+}
+
+function getElementText(element: HTMLElement) {
+ return 'innerText' in element
+ ? element.innerText
+ : // TS thinks element.innerText always exists, however it doesn't in jest/jsdom enviornment
+ // @ts-ignore-next-line
+ element.textContent || undefined;
+}
+
+const ObservedCell: FunctionComponent<{
+ renderCellValue: EuiDataGridInMemoryRendererProps['renderCellValue'];
+ onCellRender: EuiDataGridInMemoryRendererProps['onCellRender'];
+ i: number;
+ column: EuiDataGridColumn;
+}> = ({ renderCellValue, i, column, onCellRender }) => {
+ const [ref, setRef] = useState();
+
+ useEffect(() => {
+ if (ref) {
+ // this is part of React's component lifecycle, onCellRender->setState are automatically batched
+ onCellRender(i, column, getElementText(ref));
+ const observer = new MutationObserver(() => {
+ // onMutation callbacks aren't in the component lifecycle, intentionally batch any effects
+ enqueue(onCellRender.bind(null, i, column, getElementText(ref)));
+ });
+ observer.observe(ref, {
+ characterData: true,
+ subtree: true,
+ attributes: true,
+ childList: true,
+ });
+
+ return () => {
+ observer.disconnect();
+ };
+ }
+ }, [ref]);
+
+ const CellElement = renderCellValue as JSXElementConstructor<
+ CellValueElementProps
+ >;
+
+ return (
+
+
+
+ );
+};
+
export const EuiDataGridInMemoryRenderer: FunctionComponent<
EuiDataGridInMemoryRendererProps
-> = ({ columns, rowCount, renderCellValue, onCellRender }) => {
+> = ({ inMemory, columns, rowCount, renderCellValue, onCellRender }) => {
const [documentFragment] = useState(() => document.createDocumentFragment());
const rows = useMemo(() => {
const rows = [];
- const CellElement = renderCellValue as JSXElementConstructor<
- CellValueElementProps
- >;
-
for (let i = 0; i < rowCount; i++) {
rows.push(
- {columns.map(column => (
-
-
- {(ref, text) => {
- useEffect(() => {
- if (text != null) {
- onCellRender(i, column, text);
- }
- }, [text]);
- return (
-
-
-
- );
- }}
-
-
- ))}
+ {columns
+ .map(column => {
+ const skipThisColumn =
+ inMemory.skipColumns &&
+ inMemory.skipColumns.indexOf(column.id) !== -1;
+
+ if (skipThisColumn) {
+ return null;
+ }
+
+ return (
+
+ );
+ })
+ .filter(cell => cell != null)}
);
}
return rows;
- }, [columns, rowCount, renderCellValue]);
+ }, [columns, rowCount, renderCellValue, onCellRender]);
return createPortal(
{rows},
diff --git a/src/components/datagrid/data_grid_schema.ts b/src/components/datagrid/data_grid_schema.ts
index 9dcc26f1b2e..68c629d8fb7 100644
--- a/src/components/datagrid/data_grid_schema.ts
+++ b/src/components/datagrid/data_grid_schema.ts
@@ -113,6 +113,7 @@ export function useDetectSchema(
// for each row, score each value by each detector and put the results on `columnSchemas`
const rowIndices = Object.keys(inMemoryValues);
+
for (let i = 0; i < rowIndices.length; i++) {
const rowIndex = rowIndices[i];
const rowData = inMemoryValues[rowIndex];
diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts
index 5691e1bf472..9fd29ce20fe 100644
--- a/src/components/datagrid/data_grid_types.ts
+++ b/src/components/datagrid/data_grid_types.ts
@@ -41,23 +41,25 @@ export interface EuiDataGridSorting {
columns: Array<{ id: string; direction: 'asc' | 'desc' }>;
}
-/*
-Given the data flow Filtering->Sorting->Pagination:
-Each step can be performed by service calls or in-memory by the grid.
-However, we cannot allow any service calls after an in-memory operation.
-E.g. if Pagination requires a service call the grid cannot perform
-in-memory Filtering or Sorting. This means a single value representing the
-service / in-memory boundary can be used. Thus there are four states for in-memory:
-* false - all service calls
-* "pagination" - only pagination is performed in-memory
-* "sorting" - sorting & pagination is performed in-memory
-* "filtering" - all operations are performed in-memory, no service calls
+export interface EuiDataGridInMemory {
+ /**
+ Given the data flow Filtering->Sorting->Pagination:
+ Each step can be performed by service calls or in-memory by the grid.
+ However, we cannot allow any service calls after an in-memory operation.
+ E.g. if Pagination requires a service call the grid cannot perform
+ in-memory Filtering or Sorting. This means a single value representing the
+ service / in-memory boundary can be used. Thus there are four states for in-memory's level:
+ * "enhancements" - no in-memory operations, but use the available data to enhance the grid
+ * "pagination" - only pagination is performed in-memory
+ * "sorting" - sorting & pagination is performed in-memory
+ * "filtering" - all operations are performed in-memory, no service calls
*/
-export type EuiDataGridInMemory =
- | boolean
- | 'pagination'
- | 'sorting'
- | 'filtering';
+ level: 'enhancements' | 'pagination' | 'sorting' | 'filtering';
+ /**
+ * Array of column ids for in-memory processing to skip
+ */
+ skipColumns?: string[];
+}
export interface EuiDataGridInMemoryValues {
[key: string]: { [key: string]: string };
diff --git a/src/components/datagrid/style_selector.tsx b/src/components/datagrid/style_selector.tsx
index 2d41696cb94..e58f77f41b6 100644
--- a/src/components/datagrid/style_selector.tsx
+++ b/src/components/datagrid/style_selector.tsx
@@ -1,4 +1,4 @@
-import React, { FunctionComponent, useState } from 'react';
+import React, { ReactElement, useState } from 'react';
import { EuiDataGridStyle } from './data_grid_types';
import { EuiI18n } from '../i18n';
// @ts-ignore-next-line
@@ -32,7 +32,7 @@ const densityStyles: { [key: string]: Partial } = {
export const useStyleSelector = (
initialStyles: EuiDataGridStyle
-): [FunctionComponent<{}>, EuiDataGridStyle] => {
+): [ReactElement, EuiDataGridStyle] => {
// track styles specified by the user at run time
const [userGridStyles, setUserGridStyles] = useState({});
@@ -54,7 +54,7 @@ export const useStyleSelector = (
...userGridStyles,
};
- const StyleSelector = () => (
+ const styleSelector = (
);
- return [StyleSelector, gridStyles];
+ return [styleSelector, gridStyles];
};