How to make a datatable display which is dropdown driven in Plotly Dash app?

I am trying to display the contents of a csv file in the form of a table in dash app. The file whose content is to be displayed will be selected by the user from a the dropdown. The dropdown is getting the files from a location which is again user given. Below is my code:-

import dash
from dash import dcc, Input, Output, html, dash_table
import plotly.express as px
import pandas as pd
import os
#import plotly
import plotly.graph_objects as go


# ======================== Dash App
app = dash.Dash(__name__)

# ======================== Getting input of directory and Latest filename
PATH = str(input("Enter Full file path"))  # Use your path

# Fetch all files in path
fileNames = os.listdir( PATH )

# Filter file name list for files ending with .csv
fileNames = [file for file in fileNames if '.csv' in file]

print(fileNames)



# ======================== App Layout

app.layout = html.Div([
       html.H1('Table Content', style={'text-align': 'center', 'background-color': '#ede9e8'}),
       html.Div([
            dcc.Dropdown(id='DropDown_FileName',
                options=[
                         {'label': i, 'value': i} for i in fileNames
                        ],
               # value=fileNames,
                placeholder='Select a File',
                multi=False,
                clearable=False
                ),
            ]),

       
        html.Div([
            dash_table.DataTable(id='tblData'),
        ]),
                      ])


@app.callback(
    [Output('tblData', 'data')],
    [Input('DropDown_FileName', 'value')]
)


def update_figure(DropDown_FileName):
    # ======================== Reading Selected csv file

        analytics = pd.read_csv( PATH + DropDown_FileName )
        analytics['Comb_wgt']=analytics.Samples*analytics.Average
        print(analytics)


    # ======================== Plotly Table

        tblData = dash_table.DataTable(
            data=analytics.to_dict('records'),
            columns=[{"name": i, "id": i} for i in (analytics.columns)],
            )

        return (tblData)




if __name__ == '__main__':
        app.run_server()

I am trying to display the contents of a csv file in the form of a table in dash app. The file whose content is to be displayed will be selected by the user from a the dropdown. The dropdown is getting the files from a location which is again user given. Below is my code:-

import dash
from dash import dcc, Input, Output, html, dash_table
import plotly.express as px
import pandas as pd
import os
#import plotly
import plotly.graph_objects as go


# ======================== Dash App
app = dash.Dash(__name__)

# ======================== Getting input of directory and Latest filename
PATH = str(input("Enter Full file path"))  # Use your path

# Fetch all files in path
fileNames = os.listdir( PATH )

# Filter file name list for files ending with .csv
fileNames = [file for file in fileNames if '.csv' in file]

print(fileNames)



# ======================== App Layout

app.layout = html.Div([
       html.H1('Table Content', style={'text-align': 'center', 'background-color': '#ede9e8'}),
       html.Div([
            dcc.Dropdown(id='DropDown_FileName',
                options=[
                         {'label': i, 'value': i} for i in fileNames
                        ],
               # value=fileNames,
                placeholder='Select a File',
                multi=False,
                clearable=False
                ),
            ]),

       
        html.Div([
            dash_table.DataTable(id='tblData'),
        ]),
                      ])


@app.callback(
    [Output('tblData', 'data')],
    [Input('DropDown_FileName', 'value')]
)


def update_figure(DropDown_FileName):
    # ======================== Reading Selected csv file

        analytics = pd.read_csv( PATH + DropDown_FileName )
        analytics['Comb_wgt']=analytics.Samples*analytics.Average
        print(analytics)


    # ======================== Plotly Table

        tblData = dash_table.DataTable(
            data=analytics.to_dict('records'),
            columns=[{"name": i, "id": i} for i in (analytics.columns)],
            )

        return (tblData)




if __name__ == '__main__':
        app.run_server()


Using the above code, I am able to get the data on console(shared below), but the data table is not getting displayed. The main issue, I suppose is how I am calling the table component in the aap layout. I am using pycharm as IDE with all latest version of modules. Can someone please look into this. Thanks in advance.

*DataTable(data=[{'A': 'Value', 'B': Value, 'C': Value, 'C': Value}, {'A': 'Value', 'B': Value, 'C': Value, 'D': Value}, .... so on.

Hi @Himanshu_Shukla and welcome to the community!

In your callback, you are returning the output to the data attribute of your datatable which expects a dictionary of data df.to_dict('record')

However below you are returning the entire DataTable which is not the expected value to the property data

You can either chose to return only the dataframe

data=analytics.to_dict('records')
return data

Or change the property of the callback output to children of the parent div which holds the datatable in your layout and keep same return statement which returns the entire datatable.

html.Div(id='datatable-div')

@app.callback(
    Output('datatable-div', 'children'),
    Input('DropDown_FileName', 'value')
)
1 Like

Hi @atharvakatre,

Thank you for welcoming me and providing the response.
I tired both the approaches mentioned by you, and below are the outputs:

With first : choosing to return only the dataframe- Code runs without error but no table is getting rendered on the dashboard. But the call shows http 200 as the response code from localserver end.

With second: changing the output of callback to children, I am facing error.
raise SchemaTypeValidationError(value, full_schema, path, expected_type)
dash._grouping.SchemaTypeValidationError: Schema: [<Output tblData.children>]
Path: ()
Expected type: (<class ‘tuple’>, <class ‘list’>)
Received value of type <class ‘dash.dash_table.DataTable.DataTable’>:
DataTable(data=[{‘…<complete dataframev in the form of dict (as mentioned in the original question)>…’}]
127.0.0.1 - - [Date & Time] “POST /_dash-update-component HTTP/1.1” 500 -

Can you please suggest something else or am I missing something here.

@Himanshu_Shukla oh sorry I missed a few details in my previous response.

With the first method, you must have the column attribute define in the datatable in your layout. The callback just sends back the df but the datatable doesn’t know which columns to map the df on.

html.Div([
            dash_table.DataTable(id='tblData'),
            columns=[{"name": i, "id": i} for i in (analytics.columns)],
        ])

The error from the second method could be due to placing the Output and Input statements inside a list, this is no longer required in Dash callbacks.

Change this:

to this (without []):

@app.callback(
    Output('tblData', 'data'),
    Input('DropDown_FileName', 'value')
)
1 Like

Hi @atharvakatre,

I used the second approach, and it works. Many thanks for the same.
Also I am unable to understand the first method though.

Further more, I have to plot a trend chart for all the .csv files present in a directory(using only the selected columns for the .csv files. Note: All csv fiels have same columns, different values.) using plotly express, and add it to this same dashboard as the table display. I am able to make them as a separate figure using matplotlib but integrating the figure with dashboard is where I am stuck.

I think I will start a new thread for this today itself. Hope you can help me there as well.

Thank Again.
Regards,
Himanshu Shukla

1 Like