Create Dynamic Cell Templates with Dropdowns in React Spreadsheet

22 Jul 20269 minutes to read

You can add templates to cells in the React Spreadsheet Editor component by dynamically assigning a custom template property directly to individual cells. When a cell has this custom template property, you can use the beforeCellRender event to append the desired template element to the cell.

The following sample demonstrates how to insert a Syncfusion Dropdown component into Spreadsheet cells using this custom template property. Additionally, a custom ribbon item named “DropDown List” is included under a new “Template” ribbon tab. When this ribbon item is selected, the Spreadsheet dynamically inserts a dropdown into the currently active cell.

import * as React from 'react';
import { createRoot } from 'react-dom/client';
import { SpreadsheetComponent, getCellIndexes, getCell, setCell } from '@syncfusion/ej2-react-spreadsheet';
import { DropDownList } from '@syncfusion/ej2-dropdowns';

function App() {
  let spreadsheet = null;
  const spreadsheetRef = React.useRef(null);

  const dropDownOptions = [10, 20, 30, 40, 50, 60];

  const onCreated = () => {
    spreadsheet = spreadsheetRef.current;
    if (!spreadsheet) return;

    // Custom template tab to add dropdown to cell.
    spreadsheet.addRibbonTabs([{ header: { text: 'Template' }, content: [{
      text: 'DropDown List', click: () => {
        if (!spreadsheet) return;
        const sheet = spreadsheet.getActiveSheet();
        const [rowIdx, colIdx] = getCellIndexes(sheet.activeCell);
        const cellModel = getCell(rowIdx, colIdx, sheet);
        const cellEle = spreadsheet.getCell(rowIdx, colIdx);
        if (cellModel && cellModel.template === 'dropdown-list') return;
        addDropDownlist(cellEle, dropDownOptions);
      }
    }] }]);

    spreadsheet.setRowsHeight(35, ['1:100']);
    // Rendering dropdown list for a specific range initially.
    const activeSheet = spreadsheet.getActiveSheet();
    for (let colIdx = 0; colIdx <= 3; colIdx++) {
        setCell(0, colIdx, activeSheet, { template: 'dropdown-list' }, true);
    }
    spreadsheet.resize();
  };

  // Triggers before the cell is appended to the DOM.
  const beforeCellRender = (args) => {
    if (args.rowIndex !== undefined && args.colIndex !== undefined) {
      // To render dropdown if template property 'dropdown-list' is set.
      if (args.cell && args.cell.template === 'dropdown-list') {
        addDropDownlist(args.element, dropDownOptions);
      }
    }
  };

  // To render the dropdown list.
  const addDropDownlist = (element, legendOptions) => {
    element.innerHTML = '';
    const inputEle = document.createElement("input");
    element.appendChild(inputEle);
    new DropDownList({
      placeholder: 'Select a value',
      dataSource: legendOptions,
      cssClass: 'e-dropdown-list',
      change: (event)=>{
        spreadsheetRef.current.updateCell({value: event.value.toString()}, ( spreadsheet.getActiveSheet()).activeCell);
      }
    }, inputEle);
  };

  return (
    <SpreadsheetComponent
      ref={spreadsheetRef}
      created={onCreated}
      beforeCellRender={beforeCellRender}
    />
  );
}

export default App;

const root = createRoot(document.getElementById('root'));
root.render(<App />);
import * as React from 'react';
import { createRoot } from 'react-dom/client';
import { SpreadsheetComponent, getCellIndexes, getCell, setCell } from '@syncfusion/ej2-react-spreadsheet';
import { DropDownList } from '@syncfusion/ej2-dropdowns';

function App(): React.ReactElement {
  let spreadsheet: SpreadsheetComponent = null;
  const spreadsheetRef = React.useRef<SpreadsheetComponent>(null);

  const dropDownOptions: number[] = [10, 20, 30, 40, 50, 60];

  const onCreated = (): void => {
    spreadsheet = spreadsheetRef.current;
    if (!spreadsheet) return;

    // Custom template tab to add dropdown to cell.
    spreadsheet.addRibbonTabs([{ header: { text: 'Template' }, content: [{
      text: 'DropDown List', click: () => {
        if (!spreadsheet) return;
        const sheet: any = spreadsheet.getActiveSheet();
        const [rowIdx, colIdx]: number[] = getCellIndexes((sheet as any).activeCell);
        const cellModel: any = getCell(rowIdx, colIdx, sheet as any);
        const cellEle: HTMLElement = spreadsheet.getCell(rowIdx, colIdx) as HTMLElement;
        if (cellModel && (cellModel as any).template === 'dropdown-list') return;
        addDropDownlist(cellEle as any, dropDownOptions);
      }
    }] }]);

    spreadsheet.setRowsHeight(35, ['1:100']);
    // Rendering dropdown list for a specific range initially.
    const activeSheet: any = spreadsheet.getActiveSheet();
    for (let colIdx = 0; colIdx <= 3; colIdx++) {
        setCell(0, colIdx, activeSheet as any, { template: 'dropdown-list' } as any, true);
    }
    spreadsheet.resize();
  };

  // Triggers before the cell is appended to the DOM.
  const beforeCellRender = (args: any): void => {
    if (args.rowIndex !== undefined && args.colIndex !== undefined) {
      // To render dropdown if template property 'dropdown-list' is set.
      if (args.cell && args.cell.template === 'dropdown-list') {
        addDropDownlist(args.element as HTMLElement, dropDownOptions);
      }
    }
  };

  // To render the dropdown list.
  const addDropDownlist = (element: HTMLElement, legendOptions: number[]): void => {
    element.innerHTML = '';
    const inputEle: HTMLInputElement = document.createElement("input");
    element.appendChild(inputEle);
    new DropDownList({
      placeholder: 'Select a value',
      dataSource: legendOptions,
      cssClass: 'e-dropdown-list',
      change: (event: any)=>{
        spreadsheetRef.current.updateCell({value: event.value.toString()}, ( spreadsheet.getActiveSheet() as any).activeCell);
      }
    }, inputEle);
  };

  return (
    <SpreadsheetComponent
      ref={spreadsheetRef}
      created={onCreated}
      beforeCellRender={beforeCellRender}
    />
  );
}

export default App;

const root = createRoot(document.getElementById('root')!);
root.render(<App />);