Search code examples
pythonplotly-dash

Chain callback in Dash with same output


Problem: Figure still displays old trace burned into graph (Dash 2.7). To fix this I want to return an empty graph and then the updated graph to the same graph component, using callbacks.

A callback can't trigger itself which presents and issue for all my solutions to the problem.

EG.

@app.callback(
    Output('graph', 'figure'),
    Output('reset-graph', 'data'),
    Input('reset-graph', 'data'),
    Input('button','n_clicks')
)
def click(reset, button):
    if reset:
        return make_fig(), False
    
    trig = str(ctx.triggered_id)
    if trig == 'button':
        return {}, True
    else:
        raise PreventUpdate

This will not work as the callback will not trigger itself.

EDIT: Clarity. Also this was an issue with Dash 2.7


Solution

  • I don't fully understand your issue, what is your problem with this?

    @app.callback(
        Output('graph', 'figure'),
        Input('button','n_clicks')
    )
    def click(click):
        return make_fig()
        
    

    If for some reason, you want to create an empty figure, then update. You can use a 2nd callback (1st will delete the current figure, the 2nd will create a new one).

    It can actually be done in one callback, but for clarity, I think this approach is easier. You need to add the allow_duplicate=True in the graph.figure Output so it can be updated from a different callback.

    The first callback use the button as input, then sets the empty graph and update the contents of a new div intermediate_step, that is updated with whatever n_clicks is.

    Then, intermediate_step.children will be used as an input of another callback that will update graph.figure with a new graph.

    @app.callback( 
        Output('graph', 'figure', allow_duplicate=True),
        Output('intermediate_step', 'children'),
        Input('button','n_clicks')
    )
    def click(n_clicks):
        return dict(), n_clicks
    
    @app.callback( 
        Output('graph', 'figure'),
        Input('intermediate_step','children')
    )
    def new_graph(n_click):
        return make_fig()