Is this Dash DataTable week? It seems so, and I also have a question regarding conditional formatting

Hello all,
It seems that suddenly there are a lot of discussions regarding Dash DataTable, and it happens I’m working on one page for a dashboard that needs some conditional formatting.

The problem? I can’t get it to work, not even going through the examples

Here is my code:

# -*- coding: utf-8 -*-
# author: Jorge Gomes for VOST Portugal

# PROCIV CHECKER - CURRENT SITUATION  LAST 30  MINUTES

# ------------------------------
#       IMPORT LIBRARIES
# ------------------------------

# ---------- IMPORT BASIC LIBRARIES ------------

import json
import requests
import pandas as pd 
import datetime as dt 
from datetime import datetime, timedelta, date 

# ---------- IMPORT PLOTLY LIBRARIES ------------
import plotly.express as px
import plotly.graph_objects as go
import plotly.io as pio

# ---------- IMPORT DASH LIBRARIES ------------
import dash
import dash_daq as daq
from dash import Input, Output, dcc, html, callback, dash_table 
import dash_bootstrap_components as dbc


app = dash.Dash(
    external_stylesheets=[dbc.themes.CYBORG],
    title='VOSTPT:DASHBOARD',update_title=None,
    meta_tags=[{"name": "viewport", "content": "width=device-width, initial-scale=1"}],
)



    # Sample Data 
    df_dash = pd.read_csv('https://docs.google.com/spreadsheets/d/e/2PACX-1vQyC-cE62nCwUDF02mlmRkSTKnu__RH32l211ZPH2ocmG8X7H9lHRtDhC_VCiFSyVdOU-HRIrrweXnv/pub?gid=896695162&single=true&output=csv')

# Convert datetime column  to Date Time format 
df_dash['dateTime.sec'] = pd.to_datetime(df_dash['dateTime.sec'], unit='s')
# Check last timestamp in the dataframe 
last_ts =  df_dash["dateTime.sec"].iloc[-1]
# Set variable with last timestamp minus 30 minutes
 first_ts = last_ts - pd.Timedelta(30, 'minutes')

# Create dataframe with the last 30 minutes of records 
 last_30_df = df_dash[df_dash['dateTime.sec'] >= first_ts]
# Create dataframe with only the desired columns
table_df = last_30_df.loc[:,["hour","status","district","concelho","localidade","natureza"]]
# Create hexadecimal symbol
hex_symbol = "#"
# Create new column that adds the hex symbol to the value on statusColor column 
last_30_df['row_color'] = hex_symbol + last_30_df['statusColor']

app.layout = html.Div(
    [
    dbc.Row(
            [
            dcc.Interval(id='updater_component',interval=40*1000,n_intervals=0),  
            dbc.Col(html.H5(" ",style={"color":"black"}),xs=12, sm=12, md=12, lg=12, xl=2,),
            dbc.Col(html.H5(id='dispatch',style={"color":"yellow"}),xs=12, sm=12, md=12, lg=12, xl=2,),
            dbc.Col(html.H5(id='arrival',style={"color":"orange"}),xs=12, sm=12, md=12, lg=12, xl=2,),
            dbc.Col(html.H5(id='ongoing',style={"color":"red"}),xs=12, sm=12, md=12, lg=12, xl=2,),
            dbc.Col(html.H5(id='resolution',style={"color":"green"}),xs=12, sm=12, md=12, lg=12, xl=2,),
            dbc.Col(html.H5(id='conclusion',style={"color":"gray"}),xs=12, sm=12, md=12, lg=12, xl=2,),      
            ],
        ),
    dbc.Row(
            [
            dbc.Col(dcc.Graph(id="posit_map",config= {'displayModeBar': False}),xs=4),
            dbc.Col(
                dash_table.DataTable(
                    data=table_df.to_dict('records'),
                    
                    columns=[{"id":str(i),"name":str(i)} for i in table_df.columns],

                                    fixed_rows={'headers': True},
                                    style_table={'height': 500},
                                    style_as_list_view=True,
                                    style_header={
                                        'fontSize':16,
                                        'backgroundColor': 'rgb(132,141,163)'
                                    },
                                    style_cell={
                                       'fontSize':12, 'font-family':'Open Sans,sans-serif'
                                    },
                                    style_cell_conditional=[
                                                {
                                                'if': {
                                                    'column_id': 'dateTime.sec'
                                                },
                                                    'width': '6%',
                                                    'text-align':'left'
                                                },

                                                #{'if': 
                                                #    {'column_id': 'hour'
                                                #},
                                                #    'width': '3%',
                                                #    'text-align':'left'
                                                #},

                                                {'if': 
                                                    {'column_id': 'status'
                                                },
                                                    'width': '3%',
                                                    'text-align':'left',
                                                },

                                                {'if': 
                                                    {'column_id': 'district'
                                                },
                                                    'width': '5%',
                                                    'text-align':'left'
                                                },

                                                {'if': 
                                                    {'column_id': 'concelho'},
                                                    'width': '5%',
                                                    'text-align':'left'
                                                },

                                                {'if': 
                                                    {'column_id': 'freguesia'},
                                                    'width': '13%',
                                                    'text-align':'left'
                                                },

                                                {'if': 
                                                    {'column_id': 'natureza'},
                                                    'width': '5%',
                                                    'text-align':'left'
                                                }
                                    
                                    ],
                                
                                ),
                                id="posit_table", xs=6,
            ), 
            dbc.Col(xs=1),
            ],
            className="g-0",

        ),
    ],
)

# ------------------------------
#      RUN DASH APP
# ------------------------------

if __name__ == "__main__":
    app.run_server(host='0.0.0.0', debug=False, port=8082)


Basically I need that have the color that exists on last_30_df.row_color based on the value of table_df.status

I tried to test with:

{
            'if': {
                'filter_query': '{status} = Em Curso',
                'column_id': 'status'
            },
            'backgroundColor': '#654D83',
            'color': 'white'
 },
```
but I get an error message 
```
Failed component prop type: Invalid component prop `style_cell_conditional[6].if` key `filter_query` supplied to DataTable.
Bad object: {
  "filter_query": "{status} = Em Curso",
  "column_id": "status"
}
Valid keys: [
  "column_id",
  "column_type"
]

and I have been trying to make sense of why status is not recognised as a valid column ID the whole afternoon.

Any help in sorting this out would be much appreciated

Disclaimer: The solution will be used in a non-for-profit NGO project. No commercial use will be made of the solution presented

Hi @jgomes_eu

I don’t see anything obviously wrong with the code you posted. It would be helpful if you could post a complete minimal example that reproduces the error including a small amount of sample data.

1 Like

Hi @AnnMarieW! I’ve edited the original post that points to a sample data csv file.

Hi @jgomes_eu

Thanks for the mwe with data - that was helpful!
I found two things:

  • be sure to use style_data_conditional rather than style_cell_conditional
  • when there are spaces in the string add quotes around the string, for example “Em Curso”
style_data_conditional=[
    {
        'if': {
            'filter_query': '{status}= "Em Curso"',
            'column_id': 'status'
        },
        'color': 'tomato',
        'fontWeight': 'bold'
    },
]
1 Like

Hi @AnnMarieW, thank you for this tip.
However using style_data_conditional only changes the color of the text inside the cell, for the column status

My purpose was to have something more like this: every cell in the row where status is “Em Curso” to be highlighted in a different color, like in this mockup made in Illustrator

I don’t know if this is possible, and if not, I’ll go with your solution.

This is what you are looking for:

style_data_conditional=[
    {
        'if': {
            'filter_query': '{status}= "Em Curso"',
            'column_id': 'status'
        },
        'backgroundColor': 'tomato',
        'fontWeight': 'bold'
    },
]
1 Like

Thanks for the input @ljam, however that only highlights the cell in the status column, when I want the whole row to be highlighted, as in the mockup I posted above. Your solution returns this:

Screenshot 2022-04-19 at 08.20.12

Sorry you need to remove the column id to say you want to affect the whole row

style_data_conditional=[
    {
        'if': {
            'filter_query': '{status}= "Em Curso"',
        },
        'backgroundColor': 'tomato',
        'fontWeight': 'bold'
    },
]
1 Like

See example Highlighting a row with the min value in Conditional Formatting | Dash for Python Documentation | Plotly

1 Like

Thank you @ljam and @AnnMarieW for your help! That worked!

1 Like