react-datasheet

repository·master·Indexed 26 days ago

https://github.com/nadbm/react-datasheet

An Excel-like data grid for React (version 1.4.9) used to create interactive spreadsheets. It supports cell selection, keyboard navigation, copy/paste, and extensive customization through custom renderers for sheets, rows, cells, value viewers, and data editors.

Tokens
4.4K
Snippets
6
Records
22
Agent score
90%

What's inside react-datasheet

  1. Install react-datasheet

    master

    Install the react-datasheet package via npm and ensure you import the required CSS styles in your application bootstrapping process.

    $ npm install react-datasheet --save
    import ReactDataSheet from 'react-datasheet';
    // Be sure to include styles at some point, probably during your bootstrapping
    import 'react-datasheet/lib/react-datasheet.css';
  2. Configure basic react-datasheet options

    master

    The react-datasheet component accepts several configuration options to control data rendering, overflow behavior, and event handling.

    Key options include:

    • data: An Array of rows, where each row contains cell objects.
    • valueRenderer: A function function(cell, i, j) to render the visible cell value.
    • dataRenderer: A function function(cell, i, j) to render the underlying value (visible in edit mode).
    • overflow: Controls text overflow in cells. Options: 'wrap', 'nowrap', or 'clip'.
    • onCellsChanged: A handler function(arrayOfChanges[, arrayOfAdditions]) triggered on value changes, deletions, or pastes.
    • onContextMenu: A handler function(event, cell, i, j) for context menu interactions.
    • parsePaste: A function function(string) to process raw clipboard data. Should return an array of arrays of strings.
    • isCellNavigable: A function function(cell, row, col) that returns true to allow navigation to a cell.
    • handleCopy: A function function({ event, dataRenderer, valueRenderer, data, start, end, range }) to customize the clipboard string when copying cells.
  3. Override react-datasheet renderers with advanced options

    master

    You can completely override the native HTML elements and rendering logic of the datasheet using advanced options. These options accept a function or a React Component.

    Structural Renderers:

    • sheetRenderer: Renders the main sheet element (default is table).
    • rowRenderer: Renders each row element (default is tr).
    • cellRenderer: Renders each cell element (default is td).

    Content Renderers:

    • valueViewer: Customizes how cell values are displayed for every cell in the sheet.
    • dataEditor: Customizes the editor used for every cell in the sheet.

    Selection Control:

    • selected: An object { start: { i: number, j: number }, end: { i: number, j: number } } or null to control selection state.
    • onSelect: A handler function({ start, end }) triggered on selection changes.
  4. Basic Usage of ReactDataSheet

    master

    To use ReactDataSheet, provide a data prop consisting of an array of rows, where each row is an array of cell objects. Use valueRenderer to define how the cell value is displayed and onCellsChanged to handle updates (triggered by typing, double-clicking, pasting, or deleting).

    class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          grid: [
            [{ value: 1 }, { value: 3 }],
            [{ value: 2 }, { value: 4 }],
          ],
        };
      }
      render() {
        return (
          <ReactDataSheet
            data={this.state.grid}
            valueRenderer={cell => cell.value}
            onCellsChanged={changes => {
              const grid = this.state.grid.map(row => [...row]);
              changes.forEach(({ cell, row, col, value }) => {
                grid[row][col] = { ...grid[row][col], value };
              });
              this.setState({ grid });
            }}
          />
        );
      }
    }
  5. Render cells with underlying components

    master

    You can include React components directly within your cell data objects. When the cell is in edit mode, the component will be rendered.

    const grid = [
      [{
        value:  5,
        component: (
          <button onClick={() => console.log("clicked")}>
            Rendered
          </button>
        )
      }]
    ]
    <ReactDataSheet
      data={grid}
      valueRenderer={(cell) => cell.value}
    />
  6. Implement a custom Row Renderer

    master

    The rowRenderer defines the layout for each row. By default, React-DataSheet uses a <tr> element.

    Requirements:

    • You must render {props.children} within your custom renderer to ensure cells are visible.

    Supplied Props:

    • row (number): The current row index.
    • selected (Bool): true if the current row is selected.
    • cells (Array): The cells in the current row.
    • children (Array or component): The regular React props.children.
  7. Implement a custom Sheet Renderer

    master

    The sheetRenderer is responsible for the layout of the sheet's main parent component. By default, React-DataSheet uses a <table> element.

    Requirements:

    • You must render {props.children} within your custom renderer to ensure rows and cells are visible.
    • You can add to the provided className but should not overwrite or omit it unless providing your own CSS.

    Supplied Props:

    • data (Array): The same data array used by the main ReactDataSheet component.
    • className (String): Classes to apply to your top-level element.
    • children (Array or component): The regular React props.children.
  8. Use valueRenderer and dataRenderer for cell formatting

    master

    Each cell has two display modes:

    1. View mode: Uses valueRenderer to show data to the user.
    2. Edit mode: Uses dataRenderer to provide the value for the input field. dataRenderer must return a string.

    Both callbacks receive (cell, row, col) as arguments, allowing for coordinate-based formatting (e.g., formatting a specific column as a date).

    const grid = [
       [{value:  5, expr: '1 + 4'}, {value:  6, expr: '6'}, {value: new Date('2008-04-10')}],
       [{value:  5, expr: '1 + 4'}, {value:  5, expr: '1 + 4'}, {value: new Date('2004-05-28')}]
    ]
    const onCellsChanged = (changes) => changes.forEach(({cell, row, col, value}) => console.log("New expression :" + value))
    <ReactDataSheet
      data={grid}
      valueRenderer={(cell, i, j) => j == 2 ? cell.value.toDateString() : cell.value}
      dataRenderer={(cell, i, j) => j == 2 ? cell.value.toISOString() : cell.expr}
      onCellsChanged={onCellsChanged}
    />
  9. Implement a custom Cell Renderer

    master

    The cellRenderer creates the container for each cell. The default renders a <td> element.

    Requirements:

    • You must render {props.children} within your custom renderer to see the cell's data.
    • You must hook up the provided event handlers (onMouseDown, onMouseOver, onDoubleClick, onContextMenu) to maintain built-in selection and editing behaviors.

    Supplied Props:

    • row (number): The current row index.
    • col (number): The current column index.
    • cell (Object): The cell's raw data structure.
    • className (String): Classes to apply to your cell element.
    • style (Object): Generated styles that should be applied to your cell element (may be null/undefined).
    • selected (Bool): Is the cell currently selected.
    • editing (Bool): Is the cell currently being edited.
    • updated (Bool): Was the cell recently updated.
    • attributesRenderer (func): As for the main ReactDataSheet component.
    • onMouseDown (func): Important for cell selection behavior.
    • onMouseOver (func): Important for cell selection behavior.
    • onDoubleClick (func): Important for editing.
    • onContextMenu (func): Launches default content-menu handling.
    • children (Array or component): The regular React props.children.
  10. Add extra attributes to cells using attributesRenderer

    master

    Use the attributesRenderer prop to inject custom HTML attributes (like data-* attributes) into the cell markup based on the cell's data.

    const grid = [
      [{value:  1, hint: 'Valid'}, {value:  3, hint: 'Not valid'}],
      [{value:  2}, {value:  4}]
    ]
    <ReactDataSheet
      data={grid}
      valueRenderer={(cell) => cell.value}
      attributesRenderer={(cell) => (cell.hint ? { 'data-hint': cell.hint } : {})}
      ...
    />
  11. Handle data changes with onCellsChanged

    master

    The onCellsChanged(arrayOfChanges[, arrayOfAdditions]) handler is called whenever data in the grid changes (via user input, deletion, or pasting).

    The arrayOfChanges argument

    An array of objects representing changed cells. Each object contains:

    • cell: The original cell object (can be null).
    • row: Row index of the changed cell.
    • col: Column index of the changed cell.
    • value: The new cell value (usually a string, but can be any type if using a custom editor).

    The arrayOfAdditions argument

    If a user pastes data that extends beyond the current grid bounds, a second argument is provided. These objects contain the same properties as changes, but:

    • There is no cell property.
    • row or col (or both) will be outside the original grid bounds.

    Note: onChange and onPaste are deprecated handlers and should be avoided in favor of onCellsChanged.

  12. Implement a custom Value Viewer

    master

    The valueViewer displays cell data when in view mode (e.g., showing a star rating instead of a number). You can specify a valueViewer for the entire sheet or for an individual cell.

    Supplied Props:

    • value (node): The result of the valueRenderer function.
    • row (number): The current row index.
    • col (number): The current column index.
    • cell (Object): The cell's raw data structure.