Ag Grid Conditionnal Row Styling from Python callback

Hello,

I would like to set up a cell background modification when calling a callback.
In this callback, I check that all the cells in the line called by the ‘cellValueChanged’ event are valid (regex check, etc.).

Unfortunately, I can only find examples with logic written in Javascript/CSS, like here:

https://dash.plotly.com/dash-ag-grid/cell-styling

Thanks for your help.

Hello @Jocelyn,

I am not quite sure what you are after…

Could you maybe elaborate with an example of what you are trying to accomplish?

Hello jinnyzor,

I’ve created an example based on the official example : Dash Ag Grid - Getting started.

import re

from dash import Dash, html, Output, Input, callback
import dash_ag_grid as dag
import pandas as pd

df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/wind_dataset.csv")
df['id'] = df.index


def is_numeric(n):
    try:
        float(n)
        return True
    except ValueError:
        return False


def is_value_valid(name, value):
    if name == "direction":
        DIRECTION_REGEX = re.compile(r"[NSEW]{1,4}")
        return bool(DIRECTION_REGEX.match(value))

    elif name in 'strength':
        STRENGTH_RANGE_REGEX = re.compile(r"\d-\d")
        STRENGTH_END_REGEX = re.compile(r"\d\+")
        is_range_format = bool(STRENGTH_RANGE_REGEX.match(value))
        is_end_format = bool(STRENGTH_END_REGEX.match(value))
        return any([is_range_format, is_end_format])

    elif name == "frequency":
        return is_numeric(value)

    return True


def is_row_valid(row):
    REQUIRED_FIELD = ('direction', 'strength', 'frequency')
    fields_ok = []
    for name in REQUIRED_FIELD:
        if name not in row:
            return False
        fields_ok += [is_value_valid(name, row[name])]
    return all(fields_ok)


@callback(Output('get-started-example-basic', 'rowTransaction'),
          Input('get-started-example-basic', 'cellValueChanged'),
          prevent_initial_call=True)
def validation(cell):
    if is_value_valid(name=cell['colId'], value=cell['value']):
        print("ACTION TODO : delete red cell background")
        if is_row_valid(cell['data']):
            return {'update': [{**cell['data'], 'state': 'VALID'}]}
        else:
            return {'update': [{**cell['data'], 'state': 'INVALID'}]}
    else:
        if 'oldValue' in cell:
            return {'update': [{**cell['data'], 'state': 'INVALID', cell['colId']: cell['oldValue']}]}
        else:
            print("ACTION TODO : set red cell background")
            return {'update': [{**cell['data'], 'state': 'INVALID'}]}


app = Dash(__name__)

columnDefs = [
    {"field": "id", "hide": True},
    {'field': 'direction', 'editable': True},
    {'field': 'strength', 'editable': True},
    {'field': 'frequency', 'editable': True},
]

grid = dag.AgGrid(
    id="get-started-example-basic",
    rowData=df.to_dict("records"),
    columnDefs=columnDefs,
    getRowId="params.data.id",
)

app.layout = html.Div([grid])

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

In the application, there’s a callback to check that the entries are valid. If this isn’t the case, it changes the background color of the cell (not written) and resets the old valid value if it was existing.

Thanks for your help.

Have you looked into using something like this instead?

As far as the rowStyle, you cant do something like this:

getRowStyle = {
    "styleConditions": [
        {
            "condition": "params.data['state'] == 'INVALID'",
            "style": {"backgroundColor": "rgb(255,199,206, 0.9)", "color": "rgb(156,0,6)"},
        },
    ],
}