Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Table] Add onCompleteRender prop #1505

Merged
merged 19 commits into from
Aug 29, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Implement
  • Loading branch information
cmslewis committed Aug 25, 2017
commit 8d02ef2325124de6fff5f595b7698583120fd1d3
3 changes: 3 additions & 0 deletions packages/table/src/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ export class Table extends AbstractComponent<ITableProps, ITableState> {
minColumnWidth: 50,
minRowHeight: 20,
numRows: 0,
renderOptimizationMode: RenderOptimizationMode.BATCH,
renderRowHeader: renderDefaultRowHeader,
selectionModes: SelectionModes.ALL,
};
Expand Down Expand Up @@ -1022,6 +1023,7 @@ export class Table extends AbstractComponent<ITableProps, ITableState> {
fillBodyWithGhostCells,
loadingOptions,
renderBodyContextMenu,
renderOptimizationMode,
selectedRegionTransform,
} = this.props;

Expand Down Expand Up @@ -1059,6 +1061,7 @@ export class Table extends AbstractComponent<ITableProps, ITableState> {
onFocus={this.handleFocus}
onSelection={this.getEnabledSelectionHandler(RegionCardinality.CELLS)}
renderBodyContextMenu={renderBodyContextMenu}
renderOptimizationMode={renderOptimizationMode}
selectedRegions={selectedRegions}
selectedRegionTransform={selectedRegionTransform}
viewportRect={viewportRect}
Expand Down
86 changes: 70 additions & 16 deletions packages/table/src/tableBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { IContextMenuRenderer, MenuContext } from "./interactions/menus";
import { DragSelectable, ISelectableProps } from "./interactions/selectable";
import { ILocator } from "./locator";
import { Regions } from "./regions";
import { RenderOptimizationMode } from "./common/renderOptimizationMode";

export interface ITableBodyProps extends ISelectableProps, IRowIndices, IColumnIndices, IProps {
/**
Expand Down Expand Up @@ -67,6 +68,15 @@ export interface ITableBodyProps extends ISelectableProps, IRowIndices, IColumnI
* containing the `IRegion`s of interest.
*/
renderBodyContextMenu?: IContextMenuRenderer;

/**
* Dictates how cells should be rendered. Supported modes are:
* - `RenderOptimizationMode.BATCH`: renders cells in batches to improve
* performance
* - `RenderOptimizationMode.NONE`: renders cells synchronously all at once
* @default RenderOptimizationMode.BATCH
*/
renderOptimizationMode?: RenderOptimizationMode;
}

/**
Expand Down Expand Up @@ -100,6 +110,7 @@ const RESET_CELL_KEYS_BLACKLIST: Array<keyof ITableBodyProps> = [
export class TableBody extends React.Component<ITableBodyProps, {}> {
public static defaultProps = {
loading: false,
renderOptimizationMode: RenderOptimizationMode.BATCH,
};

/**
Expand Down Expand Up @@ -140,32 +151,20 @@ export class TableBody extends React.Component<ITableBodyProps, {}> {
public render() {
const {
allowMultipleSelection,
columnIndexEnd,
columnIndexStart,
grid,
numFrozenColumns,
numFrozenRows,
onFocus,
onSelection,
rowIndexEnd,
rowIndexStart,
renderOptimizationMode,
selectedRegions,
selectedRegionTransform,
} = this.props;

// render cells in batches
this.batcher.startNewBatch();
for (let rowIndex = rowIndexStart; rowIndex <= rowIndexEnd; rowIndex++) {
for (let columnIndex = columnIndexStart; columnIndex <= columnIndexEnd; columnIndex++) {
this.batcher.addArgsToBatch(rowIndex, columnIndex);
}
}
this.batcher.removeOldAddNew(this.renderNewCell);
if (!this.batcher.isDone()) {
this.batcher.idleCallback(() => this.forceUpdate());
}
const cells = (renderOptimizationMode === RenderOptimizationMode.BATCH)
? this.renderBatchedCells()
: this.renderAllCells();

const cells: Array<React.ReactElement<any>> = this.batcher.getList();
const defaultStyle = grid.getRect().sizeStyle();

const style = {
Expand Down Expand Up @@ -206,6 +205,58 @@ export class TableBody extends React.Component<ITableBodyProps, {}> {
return renderBodyContextMenu(new MenuContext(target, selectedRegions, grid.numRows, grid.numCols));
}

// Render modes
// ============

private renderBatchedCells() {
const {
columnIndexEnd,
columnIndexStart,
rowIndexEnd,
rowIndexStart,
} = this.props;

// render cells in batches
this.batcher.startNewBatch();
for (let rowIndex = rowIndexStart; rowIndex <= rowIndexEnd; rowIndex++) {
for (let columnIndex = columnIndexStart; columnIndex <= columnIndexEnd; columnIndex++) {
this.batcher.addArgsToBatch(rowIndex, columnIndex);
}
}
this.batcher.removeOldAddNew(this.renderNewCell);
if (!this.batcher.isDone()) {
this.batcher.idleCallback(() => this.forceUpdate());
}

const cells: Array<React.ReactElement<any>> = this.batcher.getList();
return cells;
}

private renderAllCells() {
const {
columnIndexEnd,
columnIndexStart,
grid,
rowIndexEnd,
rowIndexStart,
} = this.props;

const cells: Array<React.ReactElement<any>> = [];

for (let rowIndex = rowIndexStart; rowIndex <= rowIndexEnd; rowIndex++) {
for (let columnIndex = columnIndexStart; columnIndex <= columnIndexEnd; columnIndex++) {
const extremaClasses = grid.getExtremaClasses(rowIndex, columnIndex, rowIndexEnd, columnIndexEnd);
const isGhost = grid.isGhostIndex(rowIndex, columnIndex);
cells.push(this.renderCell(rowIndex, columnIndex, extremaClasses, isGhost));
}
}

return cells;
}

// Cell renderers
// ==============

private renderNewCell = (row: number, col: number) => {
const {
columnIndexEnd,
Expand Down Expand Up @@ -238,6 +289,9 @@ export class TableBody extends React.Component<ITableBodyProps, {}> {
return React.cloneElement(baseCell, { className, key, loading: cellLoading, style } as ICellProps);
}

// Callbacks
// =========

private handleSelectionEnd = () => {
this.activationCell = null; // not strictly required, but good practice
}
Expand Down