Saving Values

After editing a cell, the grid normally inserts the new value into your data using the column definition field
attribute. This covers the most common case, where the grid owns the data state and treats the data as mutable.

This page discusses alternatives to this approach.

Value Setter

A Value Setter is the inverse of a Value Getter. Where the
value getter allows getting values from your data using a function rather than a field, the value setter allows you to
set values into your data using a function rather than specifying a field.

```python
columnDefs = [
# Option 1: using field for getting and setting the value
{‘field’: ‘name’},

# Options 2: using valueGetter and valueSetter - value getter used to get data
{
    'valueGetter': {'function': 'params.data.name'},
    'valueSetter': {'function': '''
         params.data.name = params.newValue;
         return true;
         '''
                    }
}

]
```

A value setter should return True if the value was updated successfully and False if the value was not updated (
including if the value was not changed). When you return True, the grid knows it must refresh the cell.

The example below demonstrates value setters working alongside value getters (value setters are typically only used
alongside value getters). Note the following:

View the JavaScript functions used for this example.

These JavaScript functions must be added to the dashAgGridFunctions.js file in the assets folder.
See JavaScript Functions
for more information.

var dagfuncs = (window.dashAgGridFunctions = window.dashAgGridFunctions || {});

dagfuncs.valueSetterName = (params) => {
  const fullName = params.newValue;
  const nameSplit = fullName.split(" ");
  const newFirstName = nameSplit[0];
  const newLastName = nameSplit[1];
  const data = params.data;
  if (data.first_name !== newFirstName || data.last_name !== newLastName) {
    data.first_name = newFirstName;
    data.last_name = newLastName;
    // return true to tell grid that the value has changed, so it knows to update the cell
    return true;
  } else {
    // return false, the grid doesn't need to update
    return false;
  }
};

dagfuncs.valueSetterB = (params) => {
  console.log("in valuesetterb");
  const newVal = params.newValue;
  const valueChanged = params.data.b !== newVal;
  if (valueChanged) {
    params.data.b = newVal;
  }
  return valueChanged;
};

dagfuncs.valueSetterCX = (params) => {
  const newVal = params.newValue;
  if (!params.data.c) {
    params.data.c = {};
  }
  const valueChanged = params.data.c.x !== newVal;
  if (valueChanged) {
    params.data.c.x = newVal;
  }
  return valueChanged;
};

dagfuncs.valueSetterCY = (params) => {
  const newVal = params.newValue;
  if (!params.data.c) {
    params.data.c = {};
  }
  const valueChanged = params.data.c.y !== newVal;
  if (valueChanged) {
    params.data.c.y = newVal;
  }
  return valueChanged;
};
import dash_ag_grid as dag
from dash import Dash, html, callback, Input, Output
import json
import random
import pandas as pd

app = Dash(__name__)

data = {
    "first_name": ['Niall', 'John', 'Rob', 'Alberto', 'Bas', 'Joe', 'Sean'],
    "last_name": ["White", "Black", "Smith", "Jones", "Stone", "Miller", "Davis"],
    "a": random.sample(range(20), 7),
    "b": random.sample(range(20), 7),
    "c": [{"x": i, "y": i} for i in range(7)]
}
df = pd.DataFrame(data)

columnDefs = [
    {
        "headerName": 'Name',
        "valueGetter": {"function": "params.data.first_name + ' ' + params.data.last_name"},
        "valueSetter": {"function": "valueSetterName(params)"},
    },
    {
        "headerName": 'A',
        "field": 'a',
    },
    {
        "headerName": 'B',
        "valueGetter": {"function": "params.data.b"},
        "valueSetter": {"function": "valueSetterB(params)"},
        "cellDataType": 'number',
    },
    {
        "headerName": 'C.X',
        "valueGetter": {"function": "params.data.c ? params.data.c.x : undefined"},
        "valueSetter": {"function": "valueSetterCX(params)"},
        "cellDataType": 'number',
    },
    {
        "headerName": 'C.Y',
        "valueGetter": {"function": "params.data.c ? params.data.c.y : undefined"},
        "valueSetter": {"function": "valueSetterCY(params)"},
        "cellDataType": 'number',
    },
]

app.layout = html.Div(
    [
        dag.AgGrid(
            id="grid-value-setter",
            columnDefs=columnDefs,
            rowData=df.to_dict("records"),
            columnSize="sizeToFit",
            defaultColDef={"editable": True},
            dashGridOptions={"animateRows": False}
        ),
        html.Pre(id="output-value-setter")
    ]
)


@callback(
    Output("output-value-setter", "children"),
    Input("grid-value-setter", "cellValueChanged"),
    Input("grid-value-setter", "virtualRowData"),
)
def update(changed, data):
    return json.dumps(data, indent=2)


if __name__ == "__main__":
    app.run(debug=True)