About conditional formatting of dash_table.DataTable: Is it possible to assign selected colors (dcc.RadioItems) to DataTable-cells by clicking on them?

Hello again!

So lately I have been working with dash_table.DataTables and I have been trying to find a way how to assign given colors on selected_cells of DataTables depending on what “color button” in dcc.RadioItems form would be chosen. (see figure above)

I should say that it is my first time dealing with a conditional formatting issue, I have no idea how to approach the style_data_conditional - variable. I did read that doc article in Conditional Formatting | Dash for Python Documentation | Plotly , but based on what is written there about style_data_conditional or style_cell_conditional , I could only find out that the background color of cells can be formatted depending on what column (or row) that cell is located, or through comparing values with cells of neighboring columns etc.
But nowhere could I find something about coloring selected_cells based on “what color” has currently been selected for coloring (whether it be through the value-component of dcc.RadioItems, or of checkmarks etc.)

So if I have this kind of DataTable in the app.layout:

datatable = [
                            dash_table.DataTable( 
                            
                            id='data_table_colored',
                            columns=cols,

                            style_header={
                                'backgroundColor': '#f2f2f2',
                                'fontWeight': 'bold',
                                'textAlign': 'left'
                            },
                            style_table={
                                'maxHeight': '215px',
                            },
                            style_cell={
                                'height': 'auto',
                                # all three widths are needed
                                'minWidth': '50px', 'width': '50px', 'maxWidth': '50px',
                                'whiteSpace': 'normal'
                            },
                            
                            style_data_conditional= [    # just for styling the DataTable ;  a silver-white-color pattern
                                                    {
                                                        'if': {'row_index': i, 'column_id': str(j)},
                                                        'backgroundColor': 'rgb(248, 248, 248)'
                                                    }
                                                    for i in grey_rows1 for j in grey_cols1
                                                                    ] +
                                                  [
                                                    {
                                                        'if': {'row_index': i, 'column_id': str(j)},
                                                        'backgroundColor': 'rgb(248, 248, 248)'
                                                    }
                                                    for i in grey_rows2 for j in grey_cols2
                                                 ],

                                                               ),
                        ]

and I use this color selection switch, just like in the figure above:

switch = [
                            dcc.RadioItems(
                                id='colors_switch',
                                options=[
                                    {'label': 'Red', 'value': 'red'},
                                    {'label': 'Green', 'value': 'green'},
                                    {'label': 'Yellow', 'value': 'yellow'},
                                    {'label': 'Blue', 'value': 'blue'},
                                ],
                                value='red',
                                labelStyle={'display': 'inline-block', 'margin': '15px', 'text-align': 'center'},
                                style={'text-align': 'center', 'margin': 'auto'}
                            ),

                ] 

HOW would I connect the ‘colors_switch’ - switch with the ‘data_table_colored’ - DataTable ?
Is there any way to control the background colors of clicked DataTable - cells by the ‘value’ - components of the switch, or is it completely impossible and I can not make this thing work neither through the style_data_conditional/style_cell_conditional - formatting nor through any other means and I’d have to approach this issue in a completely different way?

I’m looking forward to an informative response, I’m very thankful for the help from the community and I’d love to hear someone’s experience with those kind of issues.

Cheers!

Stribor

EDIT: I have searched about this particular issue here on StackOverflow and on community.plotly.com but I couldn’t find any thread that was really related my issue.

Well, with a bit of :thinking: I got this to work. It uses the active_cell prop to trigger the callback and update the color of the cell. It also required updating the active cell otherwise you couldn’t see the color until you selected a different cell:

color_table_cell

from dash import Dash, html, dcc, dash_table, Output, Input, State, no_update
import plotly.express as px

df = px.data.tips()
df["id"] = df.index

app = Dash(__name__,)

app.layout = html.Div(
    [
        dcc.RadioItems(
            id="colors_switch",
            options=[
                {"label": "Red", "value": "red"},
                {"label": "Green", "value": "green"},
                {"label": "Yellow", "value": "yellow"},
                {"label": "Blue", "value": "blue"},
            ],
            value="red",
            labelStyle={
                "display": "inline-block",
                "margin": "15px",
                "text-align": "center",
            },
            style={"text-align": "center", "margin": "auto"},
        ),
        dash_table.DataTable(
            id="table",
            columns=[{"name": i, "id": i} for i in df.columns],
            data=df.to_dict("records"),
            page_size=10,
        ),
    ]
)


@app.callback(
    Output("table", "style_data_conditional"),
    Input("table", "active_cell"),
    State("colors_switch", "value"),
    State("table", "style_data_conditional"),
)
def update(active_cell, color, style):
    if active_cell is None:
        return no_update
    row = active_cell["row_id"]
    col = active_cell["column_id"]

    cell_color = [
        {
            "if": {"filter_query": "{{id}} = {}".format(row), "column_id": col},
            "backgroundColor": color,
        },
        {
            "if": {"state": "active"},
            "backgroundColor": color,
            "border": "1px solid grey",
        },
    ]

    return style + cell_color


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

2 Likes

Thank you VERY much for this solution!
Well, I had already planned to do a very complicated approach to my issue.
I was thinking about modifying the column-id's of my dash_table.DataTable, I would basically name the column-id's
with the number of “marked” cells with their colors, and write some complicated algorithms style_data_conditional etc.
But I really did not think that I could just simply modify the style_data_conditional in the app.callback like you did, so thank you very much again! :grinning:

I’m maybe gonna try my method first, and if it becomes very complicated then I will use your solution!

Cheers!