Search code examples
reactjsag-gridag-grid-react

How to store, display, and allow editing of complex objects in a React AG-Grid component?


I am trying to incorporate complex objects into my AG-Grid component. I currently just have a valueFormatter that successfully formats and displays an object in each cell. I am getting a browser warning: AG Grid: Cell data type is "object" but no value parser has been provided. Please either provide an object data type definition with a value parser, or set "colDef.valueParser", which only comes up if I add editable: true to a columnDef. Trying to edit cell values breaks the grid.

How can I correctly implement the storing, displaying, and editing of these complex objects?

For example, I want some columns to have their cells represent instances of the following object:

class Cell {
    constructor(rowCoordinates, colCoordinates, value, formattedValue, ruleDerived = false, consolidated = false) {
        this.rowCoordinates = rowCoordinates;
        this.colCoordinates = colCoordinates;
        this.formattedColCoordinates = colCoordinates.map((coordinate) => {
            return coordinate.alias;
        }).join('|');
        this.value = value;
        this.formattedValue = formattedValue;
        this.ruleDerived = ruleDerived;
        this.consolidated = consolidated;
    }
}

Should I have a value parser, value getter, and/or value setter? How can I configure them such that an object instance is associated with each cell, the object is properly displayed (this is what my valueFormatter is doing), and editing the cell modifies an attribute of that object instance?

I tried defining a valueParser like so:

const cellValueParser = (params) => {
    const cellData = params.data[params.colDef.field];
    cellData.value = params.newValue;
}

The warning goes away, but after editing the values in the grid, the cell stops displaying a value.


Solution

  • You need to configure both a value getter and a value setter. The value getter is responsible for extracting the data from your complex object, and the value setter is responsible for updating the object when the cell value is edited.

    Let's go step-by-step:

    1. Value Getter: The value getter is used to extract the value to be displayed in the cell. In your case, you want to display the formattedValue property of your Cell object.

    You can define a value getter in your column definition as follows:

    const columnDefs = [
      {
        headerName: "Column Name",
        field: "cell", // Assuming your data contains 'cell' property with the Cell object
        valueGetter: (params) => {
          return params.data.cell.formattedValue;
        },
      },
      // Other column definitions...
    ];
    
    1. Value Setter: The value setter is used to update the Cell object when a cell value is edited. This is where you need to extract the new value from the edited cell and update the corresponding property of the Cell object.
    const columnDefs = [
      // Other column definitions...
      {
        headerName: "Column Name",
        field: "cell",
        valueGetter: (params) => {
          return params.data.cell.formattedValue;
        },
        valueSetter: (params) => {
          // Assuming your data contains 'cell' property with the Cell object
          params.data.cell.formattedValue = params.newValue;
          return true; // Return true to indicate the value was successfully set.
        },
        editable: true, // Make the column editable.
      },
    ];
    

    With this setup, editing the cell will update the corresponding formattedValue property of your Cell object.

    1. Using valueParser: You don't necessarily need a value parser in this case since the valueSetter is handling the update of the complex object. However, if you still want to use a value parser, you can define it as follows:
    const columnDefs = [
      // Other column definitions...
      {
        headerName: "Column Name",
        field: "cell",
        valueGetter: (params) => {
          return params.data.cell.formattedValue;
        },
        valueSetter: (params) => {
          params.data.cell.formattedValue = params.newValue;
          return true; // Return true to indicate the value was successfully set.
        },
        valueParser: (params) => {
          return params.newValue; // Return the parsed value, you can also do additional parsing here if required.
        },
        editable: true, // Make the column editable.
      },
    ];
    

    With this setup, you should be able to store, display, and edit the Cell objects in your AG-Grid component successfully.

    Important Note: Ensure that your data contains the cell property with instances of the Cell object, and make sure to use the correct field name in the column definition's field property. Also, if the cell is not displaying any value after editing, double-check that the formattedValue property of your Cell object is being updated correctly in the valueSetter function.