Callback input issue when the number of components are not the same

Hey all,

I got a dropdown list from 1 to 5 values outputs. These values will update how many cards my dashboard will build. If two, or four, or just one, whatever…

There is a button inside every single card.

My issue: what’s the input-callback that brings me all buttons IDs and to know which of them was fired?

In other words: how do I deal with callback-inputs when the number of components are not the same when I update a list

here my code:

import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc


def make_a_card(id, n_clicks):
    return dbc.Card(
        dbc.CardBody(
            [
                html.P(
                    "Some quick example text to build.",
                    className="card-text",
                ),
                html.Button('Submit',
                            id={'type': 'button-html', 'index': n_clicks}),
            ]
        ),
        id=f"card-id-{id}",
        style={"width": "18rem"},
    )


app = dash.Dash(
    suppress_callback_exceptions=False,
    external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = dbc.Container([
    dbc.Row(
        dcc.Dropdown(options=[{'label': f"{i} card(s)", 'value': i}
                              for i in range(0, 5)],
                     value=1, id="drop", style={"width": 300})
    ),
    dbc.Row([
        dbc.Row(
            html.Div(id="card-columns")
        ),
    ]),
    dbc.Row(id="result-callback")
])


@app.callback(
    Output("card-columns", "children"),
    Input("drop", "value")
)
def call(value):
    cards = [make_a_card(i, value) for i in range(0, value)]
    return cards


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

Hi @bernarducs

To identify which button is triggered you need to use Pattern Matching Callbacks:

https://dash.plotly.com/pattern-matching-callbacks

I already know that link but spent few days trying understanding the examples and struggling how to fit it in my code. I made another read and did can find the way out. . btw, thanks

That’s the callback I was looking for:

import dash
from dash import callback_context
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State, **ALL**
import dash_bootstrap_components as dbc


def make_a_card(id):
    return dbc.Card(
        dbc.CardBody(
            [
                html.P(
                    "Some quick example text to build.",
                    className="card-text",
                ),
                html.Button('Submit',
                            **id={'type': 'button-html', 'index': id},**
**                            n_clicks=0)**,
            ]
        ),
        id=f"card-id-{id}",
        style={"width": "18rem"},
    )


app = dash.Dash(suppress_callback_exceptions=False,
                external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = dbc.Container([
    dbc.Row(
        dcc.Dropdown(options=[{'label': f"{i} card(s)", 'value': i}
                              for i in range(0, 5)],
                     value=1, id="drop", style={"width": 300})
    ),
    dbc.Row([
        dbc.Row(
            html.Div(id="card-columns")
        ),
    ]),
    dbc.Row(id="result-callback")
])


@app.callback(
    Output("card-columns", "children"),
    Input("drop", "value"),
    State("card-columns", 'children')
)
def call(value, children):
    **cards = [make_a_card(i) for i in range(0, value)]**
    return dbc.CardColumns(cards)


**@app.callback(**
**    Output('result-callback', 'children'),**
**    Input({'type': 'button-html', 'index': ALL}, 'n_clicks')**
**)**
**def display_output(values):**
**    print(callback_context.inputs)**
**    return str(values)**


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