Dash_table callback updates contents ONLY for first dropdown selection

Greetings and salutations!

I am creating a simple GUI to allow the user to display the dataframe of a local CSV file using a dropdown menu.
The dropdown menu is populated by the files with .csv extension in a generic folder.

When I first run the app, it works as expected and selecting a filename generates a datatable with all the rows/columns of that file. However, when I select a different filename from the dropdown menu, the table does not update.

Cannot find the bug in my code, so any guidance would be greatly appreciated.

import pandas as pd
import pathlib
import dash
from dash import dcc, Input, Output, html, dash_table

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

# ======================== Generic Test Results directory (for universal reuse)
output_folder = r"C:\TestStand Results"

# Filter file name list for files ending with .csv
fileNames = []
filePaths = []
for p in pathlib.Path(output_folder).glob("*.csv"):
    if p.is_file():
        fileNames.append(p.name)
        filePaths.append(p)

# ======================== App Layout
title = html.H1(
    "TestStand Data Log",
    style={"text-align": "center", "background-color": "#ede9e8"},
)
dropdown = html.Div(
    dcc.Dropdown(
        id="dropdown_filename", options=[{"label": i, "value": i} for i in fileNames]
    )
)
data_log = html.Div(id="data_log")

app.layout = html.Div([title, dropdown, data_log])


@app.callback(
    [Output("data_log", "children")],
    [Input("dropdown_filename", "value")],
)
def update_table(user_select):
    # ======================== Reading Selected csv file
    if user_select is not None:
        filepath = ""
        for path in filePaths:
            if path.name == user_select:
                filepath = path

        ts_table = pd.read_csv(filepath)

        return [dash_table.DataTable(id="data_log", data=ts_table.to_dict("records"))]


# -------------------------------------------------------------------------------------
# Run local server
if __name__ == "__main__":
    app.run_server(debug=True)

Hi, I think the issue might be that your table has the same I’d as your output div. “Data_log”. Just give the data table another Id.

Reg,
J.

2 Likes

Hi @Ash010110 welcome to the forums. As @jcuypers mentioned, the ID of the table is the issue.

I wanted to add, that you could store the file path (as string) as value to the dcc.DropDown() directly. Doing so, you won’t have to theck anything in the callback. Changes to your code:

for p in pathlib.Path(output_folder).glob("*.csv"):
    if p.is_file():
        fileNames.append(p.name)
        filePaths.append(p.resolve().as_posix())
dropdown = html.Div(
    dcc.Dropdown(
        id="dropdown_filename",
        options=[
            {"label": i, "value": j} for i, j in zip(fileNames, filePaths)
        ]
    )
)
@app.callback(
    [Output("data_log", "children")],
    [Input("dropdown_filename", "value")],
    prevent_initial_call=True
)
    ts_table = pd.read_csv(user_select)
    return [dash_table.DataTable(id="data_table_log", data=ts_table.to_dict("records"))]

Full code:

import pandas as pd
import pathlib
import dash
from dash import dcc, Input, Output, html, dash_table

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

# ======================== Generic Test Results directory (for universal reuse)
output_folder = r"C:\TestStand Results"

# Filter file name list for files ending with .csv
fileNames = []
filePaths = []
for p in pathlib.Path(output_folder).glob("*.csv"):
    if p.is_file():
        fileNames.append(p.name)
        filePaths.append(p.resolve().as_posix())

# ======================== App Layout
title = html.H1(
    "TestStand Data Log",
    style={"text-align": "center", "background-color": "#ede9e8"},
)
dropdown = html.Div(
    dcc.Dropdown(
        id="dropdown_filename",
        options=[
            {"label": i, "value": j} for i, j in zip(fileNames, filePaths)
        ]
    )
)
data_log = html.Div(id="data_log")

app.layout = html.Div([title, dropdown, data_log])


@app.callback(
    [Output("data_log", "children")],
    [Input("dropdown_filename", "value")],
    prevent_initial_call=True
)
def update_table(user_select):
    # ======================== Reading Selected csv file
    ts_table = pd.read_csv(user_select)

    return [dash_table.DataTable(id="data_table_log", data=ts_table.to_dict("records"))]


# -------------------------------------------------------------------------------------
# Run local server
if __name__ == "__main__":
    app.run_server(debug=True)
1 Like

Hi, I thought about the same but I guess the issue would be potential invalid html characters which you would need to substitute and revert. It’s not pretty currently but solid in all potential corner cases, as long as the filename has no weird stuff in it.

1 Like

Thank you for the code assist! Definitely makes it more streamlined and efficient.

That did it! I knew it was something small I was missing. . . thank you so much!

1 Like