MATCH and ALL in one callback problem

Hey!

I have 5 sets of same component groups - a dropdown and a button that selects all the dropdown options. For that I have a callback that utilizes the keyword MATCH:

@callback(
    Output({"type": "dropdown", "index": MATCH}, "value"),
    Input({"type": "button", "index": MATCH}, "n_clicks"),
    State({"type": "dropdown", "index": MATCH}, "options"),
    prevent_initial_call = True
)
def select_all_options(dropdown_clicks, values):
    return values

I want a separate button that takes all of these dropdowns and clears them. I could not figure out how to add that to this callback. I have tried a separate callback that uses the keyword ALL, but that threw and error about the components having multiple outputs in different callbacks. Any ideas? Thanks!

HI @martin.vlacil , you will have to use ALL instead of MATCH and check which button has been clicked in the callback. Here is a possible solution, I had to add the State of currently selected values to the callback.

import dash
from dash import html, dcc, Input, Output, State, ALL, ctx

app = dash.Dash(__name__)
app.layout = html.Div(
    [
        html.Div(
            [
                html.Div(
                    [
                        html.Div(
                            dcc.Dropdown(
                                id={'type': 'drop', 'index': idx},
                                options=[1, 2, 3],
                                multi=True,
                                style={'width': '100%'},
                            ),
                            style={'width': '50%'}
                        ),
                        html.Button(
                            'Click',
                            id={'type': 'btn', 'index': idx},
                            style={'width': '15%'},
                        )
                    ],
                    style={'width': '50%', 'margin-top': '30px'},
                ) for idx in range(4)   # four buttons/dropdowns
            ]
        ),
        html.Button('reset', id={'type': 'reset', 'index': 0})
    ]
)


@app.callback(
    Output({'type': 'drop', 'index': ALL}, 'value'),
    Input({'type': 'btn', 'index': ALL}, 'n_clicks'),
    Input({'type': 'reset', 'index': ALL}, 'n_clicks'),
    State({'type': 'drop', 'index': ALL}, 'options'),
    State({'type': 'drop', 'index': ALL}, 'value'),
    prevent_initial_call=True
)
def update(click, reset, options, values):
    trigger = ctx.triggered_id['type']
    idx = ctx.triggered_id['index']

    # reset button has been clicked, return list of empty lists
    if trigger == 'reset':
        return [[] for _ in options]

    # callback triggered by click of one of the other buttons
    # at index of clicked button substitute the current selection with
    # the options (select all)
    values[idx] = options[idx]

    return values


if __name__ == '__main__':
    app.run(debug=True)

That helped, thank you:)