Skip to main content Skip to footer

Using Different Cell Editors Per Row in the Same FlexGrid Column in React

Multiple editors per row in the same FlexGrid

Background:

Sometimes you want a single column in a FlexGrid to use different editors depending on which row is being edited. For example, one row might require a text editor, another might need a combo box, and yet another might use a checkbox.

You can accomplish this in FlexGrid by handling the prepareCellForEdit event and dynamically swapping the default cell editor for whatever editor suits the current row.

Steps to Complete:

  1. Handle the prepareCellForEdit event to check the row being edited.
  2. Based on the row’s data, replace the default editor with a custom editor (e.g., ComboBox, CheckBox).
  3. Ensure the selected editor value is written back to the cell on completion.

Getting Started:

Create a FlexGrid with Data

We define sample data that includes one column (type) that determines which editor should be used for the value column. We wire up the prepareCellForEdit event in React.

import React, { useRef } from 'react';
import { FlexGrid } from '@mescius/wijmo.react.grid';
import * as wjcInput from '@mescius/wijmo.input';

export default function App() {

  const gridRef = useRef(null);

  const data = [
    { type: 'text', value: 'Alpha' },
    { type: 'boolean', value: true },
    { type: 'options', value: 'Option1' },
    { type: 'text', value: 'Omega' }
  ];

  ...
  };

  return (
    <FlexGrid
      ref={gridRef}
      itemsSource={data}
      autoGenerateColumns={false}
      prepareCellForEdit={handlePrepareCellForEdit}
    >
      <FlexGrid.Column header="Type" binding="type" width={120} />
      <FlexGrid.Column header="Value" binding="value" width="*" />
    </FlexGrid>
  );
}

 

Handle the prepareCellForEdit event to check the row being edited

This intercepts the moment a cell enters edit mode so you can inspect which row and column is being edited.

grid.prepareCellForEdit.addHandler((s, e) => {
  const col = s.columns[e.col];
  const rowData = s.rows[e.row].dataItem;

  if (col.binding === 'value') {
    console.log('Editing row type:', rowData.type);
  }
});
  • e.row / e.col → tells you which cell is editing.
  • dataItem → gives you the actual row object.

 

Based on the row’s data, replace the default editor with a custom editor (e.g., ComboBox, CheckBox)

This creates and assigns a different editor depending on row data.

grid.prepareCellForEdit.addHandler((s, e) => {
  const col = s.columns[e.col];
  const rowData = s.rows[e.row].dataItem;

  if (col.binding === 'value') {

    // Clean up existing editor
    if (s.activeEditor?.dispose) {
      s.activeEditor.dispose();
    }

    if (rowData.type === 'boolean') {
      const chk = new wjcInput.CheckBox(s.hostElement);
      chk.checked = rowData.value;
      s.activeEditor = chk;

    } else if (rowData.type === 'options') {
      const cbo = new wjcInput.ComboBox(s.hostElement, {
        itemsSource: ['Option1', 'Option2', 'Option3'],
        text: rowData.value
      });
      s.activeEditor = cbo;
    }
  }
});
  • You inspect rowData.type.
  • You instantiate the appropriate control.
  • You assign it to s.activeEditor.

 

Ensure the selected editor value is written back to the cell on completion

This ensures that when the user changes the editor value, the underlying data item updates correctly.

// Example for CheckBox
chk.checkedChanged.addHandler(() => {
  rowData.value = chk.checked;
});

// Example for ComboBox
cbo.textChanged.addHandler(() => {
  rowData.value = cbo.text;
});
  • Editors must update rowData.
  • If you don’t sync data, the grid will visually update but the model won’t.

 

Combined File

export default function App() {

  const gridRef = useRef(null);

  const data = [
    { type: 'text', value: 'Alpha' },
    { type: 'boolean', value: true },
    { type: 'options', value: 'Option1' },
    { type: 'text', value: 'Omega' }
  ];

  const handlePrepareCellForEdit = (s, e) => {
    const col = s.columns[e.col];
    const rowData = s.rows[e.row].dataItem;

    // Only intervene for the "value" column
    if (col.binding === 'value') {

      // Dispose existing editor if present
      if (s.activeEditor && s.activeEditor.dispose) {
        s.activeEditor.dispose();
      }

      switch (rowData.type) {

        case 'boolean':
          // Create CheckBox editor
          const chk = new wjcInput.CheckBox(s.hostElement);
          chk.checked = rowData.value;

          chk.checkedChanged.addHandler(() => {
            rowData.value = chk.checked;
          });

          s.activeEditor = chk;
          break;

        case 'options':
          // Create ComboBox editor
          const cbo = new wjcInput.ComboBox(s.hostElement, {
            itemsSource: ['Option1', 'Option2', 'Option3'],
            text: rowData.value
          });

          cbo.textChanged.addHandler(() => {
            rowData.value = cbo.text;
          });

          s.activeEditor = cbo;
          break;

        default:
          // Default text editor
          const input = document.createElement('input');
          input.type = 'text';
          input.value = rowData.value;
          input.style.width = '100%';

          input.addEventListener('change', () => {
            rowData.value = input.value;
          });

          s.activeEditor = {
            hostElement: input,
            dispose: () => {}
          };

          break;
      }
    }
  };

 

With this React setup:

  • A single “Value” column dynamically switches editors per row.
  • Users see checkboxes, combo boxes, or text inputs depending on context.
  • The data model updates immediately when edits occur.
  • The grid layout remains consistent while editing behavior varies intelligently.

Happy coding!

Andrew Peterson

Technical Engagement Engineer