Learn how to use Dash Bio for next-gen sequencing & quality control. 🧬Register for the Oct 27 webinar.

How to add callbacks for multiple graphs automatically

In a single-page Dash app I want to show many similar graphs.

For this I have created a “factory class” which can generate many graphs.

This class exposes methods to be used in the app’s app.layout and @app.callback code. A sample app.py with two graphs looks like this:

import ...

app = dash.Dash(__name__)

graph_A = GraphFactory(feature="A")
graph_B = GraphFactory(feature="B")

app.layout = html.Div([
            graph_A.graph(),
            graph_B.graph(),
            ])

@app.callback(
    graph_A.callback_output(), graph_A.callback_inputs()
)
def update_A(value):
    return graph_A.callback_update(value)

@app.callback(
    graph_B.callback_output(), graph_B.callback_inputs()
)
def update_B(value):
    return graph_B.callback_update(value)

This works fine. However I want to display many graphs from a list of GraphFactory objects. It’s easy to create the objects and put them in the app layout:

graph_list = [ GraphFactory(feature=f) for f in feature_list ]

app.layout = html.Div([ 
            g.graph() for g in graph_list
            ])

But how can I add the many callback_output(), callback_inputs() and callback_update(value) calls?

All help is appreciated

By digging into decorators I found it myself:

You can call the decorator on the object’s callback_update function directly. So for the example from the question you can write:

for g in graph_list:
    dash_app.callback(g.callback_output(),
                      g.callback_inputs())(g.callback_update)

Please note carefully, that g.callback_update has no (), because the app.callback function is applied to the g.callback_update function/method, not as usual to its return value.

Hi! I´m facing more or less the same but I could not find a solution. I tried your approach but no success. Can you share a piece of your code? I don´t have idea where my problem is. This is what I am trying to do:

for ass in asset_list:
    id_div = 'target-%s' % ass
    app.callback(Output(id_div, 'style'),
                  [
                  Input('Button','n_clicks')])(
                        {'display':'none'})

Hi @paularl, sorry for late reply.

Start with writing a sample call back in the @app.callback notation like here:

@app.callback(
    graph_B.callback_output(), graph_B.callback_inputs()
)
def update_B(value):
    return graph_B.callback_update(value)

Then you can convert it to functional notation:

dash_app.callback(graph_B.callback_output(),
                      graph_B.callback_inputs())(graph_B.callback_update)

(Note that callback_update has no brackets here!!!)

Then replace the fixed object (here graph_B) with a variable in an iterator.

Let me know whether this helps!