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!