Creating dash Modals within Cards

Hi all,

I am creating a multi-page app that takes some input text and creates a dbc.Card with the input text. It loads these cards on-the-go. So if there are 0 cards, it does not load any. If there are 2 cards, it loads both, etc.
The layout for this part looks as follows:

layout = html.Div([
        dcc.Location(id=id, refresh=False),
        html.Div(id=id)], style=style)

These cards are created in the html.Div section.
What I want to do now, is with some cards that are created, add modals inside those cards, which will have some content that is generated by the user. I have not been able to implement this and would like to see if there are solutions for this. I have made sure that each part of the modal has a unique ID, but nothing I tried seemed to work.
I realize there are ways to have this outside of the cards, which I would be able to implement easily, but I would much rather have it inside of the cards.
Thank you

Hey @baris.yakali welcome to the forums.

I understand, you are creating content dynamically.

What are you referring to? dbc.Modal()?

Yes, I am referring to dbc.Modal()

I do not understand what are you trying to achieve. You want the modal to be opened within the bounds of the dbc.Card() ?

I want the modal to be created inside the card. So when I set the layout of the page, there are no modal and no cards. Then, when I create a card, I want a modal at the footer of the card.

Could you please show us some example code of how you create the card?

The modal itself will be shown regardless of where the corresponding code is placed.

EDIT: A quick mock-up:

from dash import Dash, Input, Output, State, html, callback, MATCH
import dash_bootstrap_components as dbc


app = Dash(
    __name__,
    external_stylesheets=[dbc.themes.BOOTSTRAP]
)


def create_modal(idx):
    return dbc.Modal(
        [
            dbc.ModalHeader(
                dbc.ModalTitle(f"Modal {idx}"),
            ),
            dbc.ModalBody(
                html.Div('Modal body')
            ),
            dbc.ModalFooter(
                dbc.Button(
                    "Cancel",
                    id={"type": "btn_cancel_modal", "index": idx},
                    className="ms-auto",
                    n_clicks=0
                )
            )
        ],
        id={"type": "modal", "index": idx},
        is_open=False,
    )


app.layout = dbc.Container(
    [
        dbc.Button(
            id="button_id",
            children="Create card"
        ),
        dbc.Container(
            id='output_container',
            children=[]
        )
    ],
    fluid=True
)


@callback(
    Output("output_container", "children"),
    Input("button_id", "n_clicks"),
    State("output_container", "children"),
    prevent_initial_call=True
)
def update_children(n_clicks, current_children):
    card = dbc.Card(
        [
            dbc.CardHeader("This is the header"),
            dbc.CardBody(
                [
                    html.H4("Card title", className="card-title"),
                    html.P("This is some card text", className="card-text"),
                ]
            ),
            dbc.CardFooter(
                children=[
                    "This is the footer",
                    dbc.Button(
                        children="Show modal",
                        id={"type": "btn_show_modal", "index": n_clicks}),
                    create_modal(n_clicks)
                ]
            )
        ],
        id={"type": "card", "index": n_clicks},
        style={"width": "18rem"},
    )

    current_children.append(card)
    return current_children


@callback(
    Output({"type": "modal", "index": MATCH}, "is_open"),
    Input({"type": "btn_show_modal", "index": MATCH}, "n_clicks"),
    prevent_initial_call=True
)
def show(_):
    return True


@callback(
    Output({"type": "modal", "index": MATCH}, "is_open", allow_duplicate=True),
    Input({"type": "btn_cancel_modal", "index": MATCH}, "n_clicks"),
    prevent_initial_call=True
)
def show(_):
    return False


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

mred pmcb

This has helped me a lot, thank you! My issue was that I was constantly creating 3 modal with the same ID, which was the cause of my page not loading. Now that you have shown me a new way of creating separate IDs, it will work. Thank you for your help!

1 Like