Hi there,
simple code, there’s a list of labels and if the list of labels updates, the options for all dropdown menus should update accordingly. I first show you how I intuitively wrote the code and tell you why:
@app.callback(
Output({'type': 'add-label-radio-input', 'index': ALL}, 'options'),
Input('label-list', 'children'),
)
def update_label_options(label_list, old_options):
"""updates options for the label selection when the label list changes.
The first element of the label list ist the label list header. Therefore the
list comprehension `labels=...` starts at label_list index 1.
Args:
label_list: children from the label list
current_dataset: current dataset info and data
Returns:
updated radio options.
"""
if not dash.callback_context.triggered[0]['value']:
raise dash.exceptions.PreventUpdate
# the props children stuff is getting the value from html.H6 element of the
# label card.
labels = [list_item['props']['children'][1]['props']['children']
for list_item in label_list[1:]]
return [{"label": label, "value": label} for label in labels]
My thinking was, that if I have a dynamically generated elements of which I want to update a dynamic number, ALL is obviously what I want to have. ALL to me implies that I want the same output to go to all these components. Therefore I thought that I can just return the desired output, in this case a list of options as shown, and dash will deliver that to all components that the pattern matching matched.
That doesn’t work though… Dash requires a list of outputs equal to the number of matched components that need to be updated. I find that a bit odd.
This is how I got it to work:
@app.callback(
Output({'type': 'add-label-radio-input', 'index': ALL}, 'options'),
Input('label-list', 'children'),
State({'type': 'add-label-radio-input', 'index': ALL}, 'options')
)
def update_label_options(label_list, old_options):
"""updates options for the label selection when the label list changes.
The first element of the label list ist the label list header. Therefore the
list comprehension `labels=...` starts at label_list index 1.
Args:
label_list: children from the label list
current_dataset: current dataset info and data
Returns:
updated radio options.
"""
if not dash.callback_context.triggered[0]['value']:
raise dash.exceptions.PreventUpdate
# the props children stuff is getting the value from html.H6 element of the
# label card.
labels = [list_item['props']['children'][1]['props']['children']
for list_item in label_list[1:]]
options = [{"label": label, "value": label} for label in labels]
return [options for why_though in range(len(old_options))]
I added the State of the matched components just to find out how many there are and create a list of outputs (all equal) of the required length. This seems to me like bad code ^^
Is this how I am supposed to use ALL matched Output?
Is there a reason for why that is so? Use cases where you want to match ALL outputs and then send different values to these outputs?! I was not able to infer the order in which matched outputs appear in the list as all got the same value anyway.
I would really appreciate some feedback/input on this. Thanks in advance!
cheers,
ZBN