How to implement a modal with Dash?

I am struggling to implement the following HTML/CSS construct (a CSS-only modal that can be toggled on button click) with Dash components:

In particular, I did not manage to express the following HTML:

<!-- Modal trigger -->
<label class="button" for="element-toggle">Launch Modal</label>
<input id="element-toggle" type="checkbox" />

Anyone got an idea how to code this with Dash? Or suggestions for a workaround?

There’s a Modal component in dash-bootstrap-components which is pretty straightforward to use with Dash.

Here’s an alternative more manual approach suggested by @mbkupfer in a different post.

1 Like

Thanks for the mention @tcbegley, but by all means I couldn’t recommend the dash bootstrap components enough. That said, my “vanilla” approach is quite old and was created before I knew about DBC. Also, it could now be refactored with callback context if you do go that route.

2 Likes

+1 for dbc.Modal, works great and is flexible.

2 Likes

Thanks, the dbc.Modal seems to work fine.

Only possible drawback is that I have been building on Bulma and now I am mixing Bulma and Bootstrap - I hope this goes without much complications.

1 Like

You can always not link the Bootstrap stylesheet and just copy across /modify the relevant bits from Bootstrap’s modal styles to a custom stylesheet if there is a clash. The main classes are probably modal and modal-open.

2 Likes

One more thing: My modal contains a html.Textarea and I would like to use the content typed in there in a callback - AFTER the modal has been closed. This seems to be a tricky thing to do - can anyone suggest a solution? It seems like the content is cleared when the modal is closed.

Maybe you could read the contents into a dcc.Store component while the modal is open, then recover it from there after the modal has been closed?

1 Like

I have just learned of the existence of dcc.Store and will try this out.

1 Like

When I try to store the contents of the html.Textarea in the dcc.Store, the valueof the Textarea is always None…

@app.callback(
    Output('memory', 'data'),
    [
        Input('interest-codes-paste-enter', 'n_clicks')
    ],
    [
        State('combi-interest-codes-paste-area', 'value'),
    ]
)
@support.logged_call
def store_pasted_codes(n_clicks, paste_content):
    print("paste content", paste_content)
    if n_clicks:
        return paste_content

I created the store at the top level of the layout:

app.layout = html.Div(
    className="container",
    children=[
        dcc.Location(id='location', refresh=False), # represents the URL bar, doesn't render anything
        dcc.Store(id='memory'), # HTML5 local storage
        navbar,
        aspect_area,
    ]
)