Issue with Updating Dash Dashboard Figure Dynamically

I’m encountering a problem with updating the figure dynamically in my Dash dashboard application. I have a callback function set up to handle click events on bars in a plot, and I want to update the figure based on the clicked data. However, the figure doesn’t seem to update as expected.

Here’s a simplified version of my code:

======================


import dash
from dash import dcc, html
import pyarrow.parquet as pq
from dash.dependencies import Input, Output
from src.generate_plot import generate_plot
from src.mapas_indiretos_entrada import read_parquet_file
from src.mapas_indiretos_entrada import mapas_indiretos_entrada


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

# parquet_file = "EFDICMSIPI-Entrada.parquet"
# file_key = f'Parquet/{parquet_file}'
# data = read_parquet_file(file_key)

parquet_file_path = 'Data/EFDICMSIPI-Entrada.parquet'
data = pq.read_table(parquet_file_path).to_pandas()

json_data = mapas_indiretos_entrada(data)

initial_figure = generate_plot(json_data)

# Define layout of the Dash app
app.layout = html.Div([
    dcc.Graph(id='bar-plot', figure=initial_figure,
              style={'width': '90%', 'height': '95vh'}  # Adjust width and height as needed
              ),
    html.Div(id='bar-click-output')
])


# Define callback function to handle click events on bars
@app.callback(
    Output('bar-click-output', 'children'),
    [Input('bar-plot', 'clickData')]
)
def handle_click_event(clickData):
    if clickData:
        x_value = clickData['points'][0]['x']
        y_value = clickData['points'][0]['y']

        filtered_data = data[data['Empresa'] == x_value].copy()
        json_data = mapas_indiretos_entrada(filtered_data)

        # Generate the updated plot with the filtered data
        updated_figure = generate_plot(json_data)

        test_to_print = f'Clicked on bar at x={x_value}, y={y_value}'
        print(test_to_print)
        return test_to_print
    else:
        test_to_print = 'No bar clicked'
        print(test_to_print)
        return test_to_print


# Run the Dash app
if __name__ == '__main__':
    app.run_server(debug=True)

====================

I’ve tried redefining the layout structure within the callback function, but it doesn’t seem to work. Can anyone help me figure out what I’m doing wrong or suggest an alternative approach to dynamically updating the figure?

Any insights or suggestions would be greatly appreciated.

Thank you!

Hey @Safwan welcome to the forums.

Your callback takes one input (clickData) and returns to one output. In this case, the output is the children of a html.Div().

If you want to update an other component in this callback, you’ll need to add a second Output() and return two arguments.

Without having checked your code otherwise, it should look more or less like this:

import dash
from dash import dcc, html, Input, Output, no_update
import pyarrow.parquet as pq
from src.generate_plot import generate_plot
from src.mapas_indiretos_entrada import read_parquet_file
from src.mapas_indiretos_entrada import mapas_indiretos_entrada


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

# parquet_file = "EFDICMSIPI-Entrada.parquet"
# file_key = f'Parquet/{parquet_file}'
# data = read_parquet_file(file_key)

parquet_file_path = 'Data/EFDICMSIPI-Entrada.parquet'
data = pq.read_table(parquet_file_path).to_pandas()

json_data = mapas_indiretos_entrada(data)

initial_figure = generate_plot(json_data)

# Define layout of the Dash app
app.layout = html.Div([
    dcc.Graph(id='bar-plot', figure=initial_figure,
              style={'width': '90%', 'height': '95vh'}  # Adjust width and height as needed
              ),
    html.Div(id='bar-click-output')
])


# Define callback function to handle click events on bars
@app.callback(
    Output('bar-click-output', 'children'),
    Output('bar-plot', 'figure'),
    [Input('bar-plot', 'clickData')]
)
def handle_click_event(clickData):
    if clickData:
        x_value = clickData['points'][0]['x']
        y_value = clickData['points'][0]['y']

        filtered_data = data[data['Empresa'] == x_value].copy()
        json_data = mapas_indiretos_entrada(filtered_data)

        # Generate the updated plot with the filtered data
        updated_figure = generate_plot(json_data)

        test_to_print = f'Clicked on bar at x={x_value}, y={y_value}'
        print(test_to_print)
        return test_to_print, updated_figure
    else:
        test_to_print = 'No bar clicked'
        print(test_to_print)
        return test_to_print, no_update


# Run the Dash app
if __name__ == '__main__':
    app.run(debug=True)

Please note, that the imports from dash.dependencies are outdated.

Thank you, that works.

Another question: can I use Flask instead of Dash? How would the code look?

Could you elaborate a bit more on that? What exactly do you want to do in Flask?

In Flask, we aim to harness its capabilities for web development, particularly in a cloud environment. I plan to build a web application that allows several users to access plots and apply filters or interactions. Is it possible to achieve this using Plotly?

Yes, dash (which is build on top of flask) is used exactly for what you describe.

You can find some examples of web applications built with dash here:

plotly is a graphing library.