Dynamically defined callback challenges

First of all a big thanks to everyone at Plotly and the community for an excellent product and information/resources available! :smiley:

I am working on an app that takes a list of system and their names and lists these as “blocks” in a grid. When a “block” is clicked some actions (filtering of a table, communicating with an API, etc.) should be executed through a callback with other_info. Initially, I tried to implement this based on the “Event”-functionality, but as this has been removed I am now working with “Input”.

Currently, I am experiencing two challenges:

1. The dynamically defined callback appears to pass one variable per “block” to the function to be executed (i.e. way more inputs than the function is expecting). As the “blocks” are dynamically defined it is no possible to “hard code” these as inputs to the function.

2. Using n_clicks necessitates keeping track of clicks on each “block” to be able to figure out which block was clicked most recently. Is there another way of handling this?

The current callback is as follows.

@app.callback(
    Output('overview-table', 'children'), 
    [Input( 'sys_number_{}'.format(sys_info.sys_number), 'n_clicks') for i, sys_info in system_df.iterrows()],
)

def update_table(n_clicks, other_info):
    # Do actions
    return html.P('text')

Reading through previous threads I am can’t seem to find a solution to the above challenge, any pointers/suggestions will be greatly appreciated!

This is something we’ve been discussing a lot lately https://github.com/plotly/dash/issues/475 but until we manage to implement that there are workarounds:

  1. for the moment you do need to hard-code them, unfortunately. You basically need to have as many blocks as you’re ever going to allow pre-created, and when the user asks for a new one you just un-hide it.

  2. check out dash.callback_context - which we need to document better, I only see it in the faq right now https://dash.plot.ly/faqs

Thanks Alex! The linked issues was an interesting read, would be a great addition to the callback-functionality.

Working through my challenge I have ended up using dcc.Link and dcc.Location passing a key variable through the url and triggering the callback performing the remaining actions (will potentially get messy later on but works for now).

In short:

app.layout = html.Div([
    dcc.Location(id='url', refresh=False),
    dcc.Link( href='/s/{}'.format(sys_number) 
]

@app.callback(
    Output('output', 'children'), 
    [Input('url', 'pathname')],
)

def update_table(pathname):
    # do things
    return result

Regarding item 2 dash.callback_context fits the bill. Thanks!