Skip to content

Commit 3c3eadf

Browse files
glsdowntcbegley
authored andcommitted
Added multiple Modals example (#672)
1 parent 2cc53d9 commit 3c3eadf

File tree

8 files changed

+282
-3
lines changed

8 files changed

+282
-3
lines changed

docs/components_page/components/__tests__/helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def rename_variable(snippet_path, suffix, variable, assign_op="="):
5050
for line in lines:
5151
if line.startswith(f"{variable} {assign_op}"):
5252
line = line.replace(
53-
f"{variable} {assign_op}", f"{variable}_{suffix} {assign_op}"
53+
f"{variable} {assign_op}", f"{variable}__{suffix} {assign_op}"
5454
)
5555
new_lines.append(line)
5656

docs/components_page/components/__tests__/test_modal.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,60 @@ def check_modal_centered_callbacks(runner):
189189
lambda: len(runner.find_elements(".modal-content")) == 0,
190190
timeout=4,
191191
)
192+
193+
194+
# ------------------------------
195+
196+
197+
def test_r_modal_toggle(dashr):
198+
r_app = load_r_app((HERE.parent / "modal" / "toggle.R"), "modal")
199+
dashr.start_server(r_app)
200+
check_modal_toggle_callbacks(dashr)
201+
202+
203+
def test_jl_modal_toggle(dashjl):
204+
jl_app = load_jl_app((HERE.parent / "modal" / "toggle.jl"), "modal")
205+
dashjl.start_server(jl_app)
206+
check_modal_toggle_callbacks(dashjl)
207+
208+
209+
def check_modal_toggle_callbacks(runner):
210+
runner.find_element("#open-toggle-modal").click()
211+
wait.until(
212+
lambda: len(runner.find_elements(".modal-content")) != 0,
213+
timeout=4,
214+
)
215+
wait.until(
216+
lambda: len(runner.find_elements("#toggle-modal-1")) == 1,
217+
timeout=4,
218+
)
219+
wait.until(
220+
lambda: len(runner.find_elements("#toggle-modal-2")) == 0,
221+
timeout=4,
222+
)
223+
224+
runner.find_element("#open-toggle-modal-2").click()
225+
wait.until(
226+
lambda: len(runner.find_elements("#toggle-modal-2")) == 1,
227+
timeout=4,
228+
)
229+
wait.until(
230+
lambda: len(runner.find_elements("#toggle-modal-1")) == 0,
231+
timeout=4,
232+
)
233+
234+
runner.find_element("#open-toggle-modal-1").click()
235+
wait.until(
236+
lambda: len(runner.find_elements("#toggle-modal-1")) == 1,
237+
timeout=4,
238+
)
239+
wait.until(
240+
lambda: len(runner.find_elements("#toggle-modal-2")) == 0,
241+
timeout=4,
242+
)
243+
244+
runner.find_elements(".modal-header > .btn-close")[0].click()
245+
wait.until(
246+
lambda: len(runner.find_elements(".modal-content")) == 0,
247+
timeout=4,
248+
)

docs/components_page/components/__tests__/test_snippets.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def test_r_snippets(dash_thread_server, dashr_server, config):
7373
r_snippet = rename_variable(
7474
r_snippet_path, i, name, assign_op="<-"
7575
)
76-
python_r_compare.append((py_snippet, r_snippet, f"{name}_{i}"))
76+
python_r_compare.append((py_snippet, r_snippet, f"{name}__{i}"))
7777

7878
if python_r_compare:
7979
assert_layouts_equal(
@@ -106,7 +106,7 @@ def test_jl_snippets(dash_thread_server, dashjl_server, config):
106106

107107
if jl_snippet_path.exists():
108108
jl_snippet = rename_variable(jl_snippet_path, i, name)
109-
python_jl_compare.append((py_snippet, jl_snippet, f"{name}_{i}"))
109+
python_jl_compare.append((py_snippet, jl_snippet, f"{name}__{i}"))
110110

111111
if python_jl_compare:
112112
assert_layouts_equal(
@@ -123,6 +123,7 @@ def test_jl_snippets(dash_thread_server, dashjl_server, config):
123123
def assert_layouts_equal(
124124
compare, runner, wrapper, port, py_runner, py_env, py_port
125125
):
126+
126127
# Get python snippet layout
127128
app = py_source_to_app(
128129
PY_WRAPPER.format(

docs/components_page/components/modal.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ To vertically center the modal on the page, set `centered=True`.
4747

4848
{{example:components/modal/centered.py:modal}}
4949

50+
## Toggle between modals
51+
52+
With some clever use of callbacks, you can also create modals that open other modals.
53+
54+
{{example:components/modal/toggle.py:modal}}
55+
5056
{{apidoc:src/components/modal/Modal.js}}
5157

5258
{{apidoc:src/components/modal/ModalHeader.js}}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
library(dashBootstrapComponents)
2+
library(dashHtmlComponents)
3+
4+
modal_1 <- dbcModal(
5+
list(
6+
dbcModalHeader(dbcModalTitle("Modal 1")),
7+
dbcModalBody("This is the content of the first modal"),
8+
dbcModalFooter(
9+
dbcButton(
10+
"Open Modal 2",
11+
id = "open-toggle-modal-2",
12+
class_name = "ms-auto",
13+
n_clicks = 0
14+
)
15+
)
16+
),
17+
id = "toggle-modal-1",
18+
is_open = FALSE
19+
)
20+
21+
modal_2 <- dbcModal(
22+
list(
23+
dbcModalHeader(dbcModalTitle("Modal 2")),
24+
dbcModalBody("This is the second modal"),
25+
dbcModalFooter(
26+
dbcButton(
27+
"Back to Modal 1",
28+
id = "open-toggle-modal-1",
29+
class_name = "ms-auto",
30+
n_clicks = 0
31+
)
32+
)
33+
),
34+
id = "toggle-modal-2",
35+
is_open = FALSE
36+
)
37+
38+
39+
modal <- htmlDiv(
40+
list(
41+
dbcButton("Open modal", id = "open-toggle-modal", n_clicks = 0),
42+
modal_1,
43+
modal_2
44+
)
45+
)
46+
47+
app$callback(
48+
output("toggle-modal-1", "is_open"),
49+
list(
50+
input("open-toggle-modal", "n_clicks"),
51+
input("open-toggle-modal-1", "n_clicks"),
52+
input("open-toggle-modal-2", "n_clicks"),
53+
state("toggle-modal-1", "is_open")
54+
),
55+
function(n0, n1, n2, is_open) {
56+
if (n0 > 0 | n1 > 0 | n2 > 0) {
57+
return(!is_open)
58+
}
59+
return(is_open)
60+
}
61+
)
62+
63+
app$callback(
64+
output("toggle-modal-2", "is_open"),
65+
list(
66+
input("open-toggle-modal-2", "n_clicks"),
67+
input("open-toggle-modal-1", "n_clicks"),
68+
state("toggle-modal-2", "is_open")
69+
),
70+
function(n2, n1, is_open) {
71+
if (n1 > 0 | n2 > 0) {
72+
return(!is_open)
73+
}
74+
return(is_open)
75+
}
76+
)
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using DashBootstrapComponents, DashHtmlComponents
2+
3+
modal_1 = dbc_modal(
4+
[
5+
dbc_modalheader(dbc_modaltitle("Modal 1")),
6+
dbc_modalbody("This is the content of the first modal"),
7+
dbc_modalfooter(
8+
dbc_button(
9+
"Open Modal 2",
10+
id = "open-toggle-modal-2",
11+
class_name = "ms-auto",
12+
n_clicks = 0,
13+
),
14+
),
15+
],
16+
id = "toggle-modal-1",
17+
is_open = false,
18+
)
19+
20+
modal_2 = dbc_modal(
21+
[
22+
dbc_modalheader(dbc_modaltitle("Modal 2")),
23+
dbc_modalbody("This is the second modal"),
24+
dbc_modalfooter(
25+
dbc_button(
26+
"Back to Modal 1",
27+
id = "open-toggle-modal-1",
28+
class_name = "ms-auto",
29+
n_clicks = 0,
30+
),
31+
),
32+
],
33+
id = "toggle-modal-2",
34+
is_open = false,
35+
)
36+
37+
38+
modal = html_div([
39+
dbc_button("Open modal", id = "open-toggle-modal", n_clicks = 0),
40+
modal_1,
41+
modal_2,
42+
])
43+
44+
callback!(
45+
app,
46+
Output("toggle-modal-1", "is_open"),
47+
Input("open-toggle-modal", "n_clicks"),
48+
Input("open-toggle-modal-1", "n_clicks"),
49+
Input("open-toggle-modal-2", "n_clicks"),
50+
State("toggle-modal-1", "is_open"),
51+
) do n0, n1, n2, is_open
52+
return n0 > 0 || n1 > 0 || n2 > 0 ? is_open == 0 : is_open
53+
end;
54+
55+
callback!(
56+
app,
57+
Output("toggle-modal-2", "is_open"),
58+
Input("open-toggle-modal-2", "n_clicks"),
59+
Input("open-toggle-modal-1", "n_clicks"),
60+
State("toggle-modal-2", "is_open"),
61+
) do n2, n1, is_open
62+
return n1 > 0 || n2 > 0 ? is_open == 0 : is_open
63+
end;
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import dash_bootstrap_components as dbc
2+
import dash_html_components as html
3+
from dash.dependencies import Input, Output, State
4+
5+
modal_1 = dbc.Modal(
6+
[
7+
dbc.ModalHeader(dbc.ModalTitle("Modal 1")),
8+
dbc.ModalBody("This is the content of the first modal"),
9+
dbc.ModalFooter(
10+
dbc.Button(
11+
"Open Modal 2",
12+
id="open-toggle-modal-2",
13+
class_name="ms-auto",
14+
n_clicks=0,
15+
)
16+
),
17+
],
18+
id="toggle-modal-1",
19+
is_open=False,
20+
)
21+
22+
modal_2 = dbc.Modal(
23+
[
24+
dbc.ModalHeader(dbc.ModalTitle("Modal 2")),
25+
dbc.ModalBody("This is the second modal"),
26+
dbc.ModalFooter(
27+
dbc.Button(
28+
"Back to Modal 1",
29+
id="open-toggle-modal-1",
30+
class_name="ms-auto",
31+
n_clicks=0,
32+
)
33+
),
34+
],
35+
id="toggle-modal-2",
36+
is_open=False,
37+
)
38+
39+
40+
modal = html.Div(
41+
[
42+
dbc.Button("Open modal", id="open-toggle-modal", n_clicks=0),
43+
modal_1,
44+
modal_2,
45+
]
46+
)
47+
48+
49+
@app.callback(
50+
Output("toggle-modal-1", "is_open"),
51+
[
52+
Input("open-toggle-modal", "n_clicks"),
53+
Input("open-toggle-modal-1", "n_clicks"),
54+
Input("open-toggle-modal-2", "n_clicks"),
55+
],
56+
[State("toggle-modal-1", "is_open")],
57+
)
58+
def toggle_modal_1(n0, n1, n2, is_open):
59+
if n0 or n1 or n2:
60+
return not is_open
61+
return is_open
62+
63+
64+
@app.callback(
65+
Output("toggle-modal-2", "is_open"),
66+
[
67+
Input("open-toggle-modal-2", "n_clicks"),
68+
Input("open-toggle-modal-1", "n_clicks"),
69+
],
70+
[State("toggle-modal-2", "is_open")],
71+
)
72+
def toggle_modal_2(n2, n1, is_open):
73+
if n1 or n2:
74+
return not is_open
75+
return is_open

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ exclude =
3030
docs/components_page/components/modal/scrollable_source.py
3131
docs/components_page/components/modal/simple.py
3232
docs/components_page/components/modal/size.py
33+
docs/components_page/components/modal/toggle.py
3334
docs/components_page/components/nav/navlink.py,
3435
docs/components_page/components/navbar/navbar.py,
3536
docs/components_page/components/offcanvas/backdrop.py,

0 commit comments

Comments
 (0)