Hi,
I’d like to have a popout appear and provide the user with instructions upon opening a page. Is there any way to do this aside from using a javascript alert (which prevents page from loading, and also does not allow for styling)?
Hi,
I’d like to have a popout appear and provide the user with instructions upon opening a page. Is there any way to do this aside from using a javascript alert (which prevents page from loading, and also does not allow for styling)?
Create a modal window. I’m implementing something similar in my application. Here is the basic gist of it:
def modal():
return html.Div(
children=[
html.Div([
html.Div(
className='modal-text',
children=[
dcc.Markdown(dedent('''
# This is the text that will be in the modal
'''))
]
),
],
id='modal',
className='modal',
style={"display": "none"},
)
And then here is the callbacks to open and close it:
# hide/show modal
@app.callback(Output('modal', 'style'),
[Input('instructions-button', 'n_clicks')])
def show_modal(n):
if n > 0:
return {"display": "block"}
return {"display": "none"}
# Close modal by resetting info_button click to 0
@app.callback(Output('instructions-button', 'n_clicks'),
[Input('modal-close-button', 'n_clicks')])
def close_modal(n):
return 0
Also, in addition to the styling you add to your modal, one quick tip is to give it a z-index of 1002. The modebar for plotly figures have a z-index of 1001 so anything less and small little gray boxes will appear.
Here is my styles I’m using (btw, I use modal for the container, and use modal-content for the text. That way I can create a darkening/raised effect between the content and the application.
.modal {
position: fixed;
z-index: 1002; /* Sit on top, including modebar which has z=1001 */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
background-color: rgba(0, 0, 0, 0.6); /* Black w/ opacity */
}
.modal-content {
margin: 40px;
height: 500px;
padding: 40px;
background-color: white;
}
Wow, thats great! Thanks.
I got your idea working as I wanted with some minor tweaks. Here is a simplified out of the box working implementation that others may find useful:
import dash
from dash.dependencies import Input, Output
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.Div([
html.H2('Thank Mbkupfer for this modal'),
html.Div([ # modal div
html.Div([ # content div
html.Div([
'This is the content of the modal',
]),
html.Hr(),
html.Button('Close', id='modal-close-button')
],
style={'textAlign': 'center', },
className='modal-content',
),
],
id='modal',
className='modal',
style={"display": "block"},
)
])
@app.callback(Output('modal', 'style'),
[Input('modal-close-button', 'n_clicks')])
def close_modal(n):
if (n is not None) and (n > 0):
return {"display": "none"}
if __name__ == '__main__':
app.run_server(debug=True)
And big thanks mbkupfer for the CSS as well, very nice effects. - copy this into your local CSS file:
.modal {
position: fixed;
z-index: 1002; /* Sit on top, including modebar which has z=1001 */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
background-color: rgba(0, 0, 0, 0.6); /* Black w/ opacity */
}
.modal-content {
margin: 90px;
padding: 30px;
background-color: white;
}
@mbkupfer @troystory89
I am building an app where I need to drilldown to detail screen (in this case a modal) from a stacked bar chart. Any way I can trigger the modal on click of a specific bar? n_clicks is not recognized with charts.
Thanks in advance
You can use the graph’s clickData
property as a callback input instead of a button as in the example above. You can find some more dcc.Graph
properties here.
Note the clickData
is a dictionary data type so you will need to use keys to index its values. Perhaps print out to the console to get a feel for how the structure looks.
Thank you for suggesting this @mbkupfer. I tried the below approach and it worked! I referred to this thread as well to store the states, as clickData will always have some value once the chart is clicked. Below is my code:
# -*- coding: utf-8 -*-
“”"
Created on Wed Mar 13 20:02:17 2019
@author: monishaj
“”"
import dash
from dash.dependencies import Input, Output, State
import dash_html_components as html
from plotly import graph_objs as go
from plotly.graph_objs import *
import dash_core_components as dcc
import json
app = dash.Dash(name)
trace1 = go.Bar(
x=[‘a’, ‘b’, ‘c’,‘d’],
y=[1.2,9.8,4.5,0.9],
name=‘A1’
)
trace2 = go.Bar(
x=[‘a’, ‘b’, ‘c’,‘d’],
y=[1.6,9.6,5.6,3.2],
name=‘A2’
)
trace3 = go.Bar(
x=[‘a’, ‘b’, ‘c’,‘d’],
y=[4.2,1.3,2.5,2.4],
name=‘A3’
)
app.layout = html.Div([
html.H2('Simple Modal'),
html.Div([
html.Div(id='modal-content'),
dcc.Graph(id='bar_plot',
figure=go.Figure(data=[trace1, trace2, trace3],
layout=go.Layout(barmode='stack',hovermode='closest')),style={'margin-left':'205px'}
)
]),
html.Div([ # modal div
html.Div([ # content div
html.P('Some Text'),
html.Button('Close',n_clicks=0, id='modal-close-button')
],
style={'textAlign': 'center', },
className='modal-content',
),
],
id='modal',
className='modal',style={"display":"none"}
),
html.Div(id='modal-button-values', children="Close:0 last:Close",style={"display":"none"})
])
@app.callback(Output(‘modal-button-values’, ‘children’),
[Input(‘bar_plot’, ‘clickData’),Input(‘modal-close-button’, ‘n_clicks’)],
[State(‘modal-button-values’, ‘children’)])
def close_modal(clickData,n,button_values):
button_values = dict([i.split(’:’) for i in button_values.split(’ ')])
l = len(clickData[‘points’][0].keys())
if l:
if n == 0:
last_clicked = "Get"
elif n is not None and n > 0:
if n > int(button_values["Close"]):
last_clicked = "Close"
elif n == int(button_values["Close"]):
last_clicked = "Get"
return "Close:{0} last:{1}".format(n,last_clicked)
@app.callback(Output(‘modal’, ‘style’),
[Input(‘modal-button-values’, ‘children’)]
)
def modal_display_status(button_values):
button_values = dict([i.split(’:’) for i in button_values.split(’ ')])
if button_values["last"] == 'Get':
return {'display': 'block'}
else:
return {'display': 'none'}
if name == ‘main’:
app.run_server(debug=True)
Can you share code in github, as the one here does not work.
You could try using Modal
from dash-bootstrap-components
instead: https://dash-bootstrap-components.opensource.faculty.ai/docs/components/modal/
Do you have any reference on showing an image by popping in a new window
when the button is clicked?
If you use the Modal
component you can just pass a html.Img
as the child.
Does this do what you want?
import dash
import dash_bootstrap_components as dbc
import dash_html_components as html
from dash.dependencies import Input, Output, State
COOKIE = "https://todaysmama.com/.image/t_share/MTU5OTEwMzkyMDIyMTE1NzAz/cookie-monster.png"
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = dbc.Container(
[
dbc.Button("Show the cookie monster", id="button"),
dbc.Modal(
[
dbc.ModalHeader("Cookies!"),
dbc.ModalBody(html.Img(src=COOKIE, style={"width": "100%"})),
],
id="modal",
is_open=False,
),
],
className="p-5",
)
@app.callback(
Output("modal", "is_open"),
[Input("button", "n_clicks")],
[State("modal", "is_open")],
)
def toggle_modal(n, is_open):
if n:
return not is_open
return is_open
if __name__ == "__main__":
app.run_server(debug=True)