def test_clsd014_input_output_callback(dash_duo): app = Dash(__name__, assets_folder="assets") app.layout = html.Div([ html.Div(id="input-text"), dcc.Input(id="input", type="number", value=0) ]) app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="input_output_callback"), Output("input", "value"), Input("input", "value"), ) app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="input_output_follower"), Output("input-text", "children"), Input("input", "value"), ) dash_duo.start_server(app) dash_duo.find_element("#input").send_keys("2") dash_duo.wait_for_text_to_equal("#input-text", "3") call_count = dash_duo.driver.execute_script("return window.callCount;") assert call_count == 2, "initial + changed once" assert dash_duo.get_logs() == []
def test_clientside_exceptions_halt_subsequent_updates(self): app = dash.Dash(__name__, assets_folder='clientside_assets') app.layout = html.Div([ dcc.Input(id='first', value=1), dcc.Input(id='second'), dcc.Input(id='third'), ]) app.clientside_callback( ClientsideFunction('clientside', 'add1_break_at_11'), Output('second', 'value'), [Input('first', 'value')], ) app.clientside_callback( ClientsideFunction('clientside', 'add1_break_at_11'), Output('third', 'value'), [Input('second', 'value')], ) self.startServer(app) test_cases = [ ['#first', '1'], ['#second', '2'], ['#third', '3'], ] for test_case in test_cases: self.wait_for_text_to_equal(test_case[0], test_case[1]) first_input = WebDriverWait(self.driver, 10).until( EC.presence_of_element_located((By.ID, 'first')) ) first_input.send_keys('1') # clientside code will prevent the update from occurring test_cases = [ ['#first', '11'], ['#second', '2'], ['#third', '3'] ] for test_case in test_cases: self.wait_for_text_to_equal(test_case[0], test_case[1]) first_input.send_keys('1') # the previous clientside code error should not be fatal: # subsequent updates should still be able to occur test_cases = [ ['#first', '111'], ['#second', '112'], ['#third', '113'] ] for test_case in test_cases: self.wait_for_text_to_equal(test_case[0], test_case[1])
def __init__(self, **kwargs): super(DashChainedServersideClientsideCallback, self).__init__(**kwargs) self.dash.layout = html.Div([ html.Label('x'), dcc.Input(id='x', value=3), html.Label('y'), dcc.Input(id='y', value=6), # clientside html.Label('x + y (clientside)'), dcc.Input(id='x-plus-y'), # server-side html.Label('x+y / 2 (serverside)'), dcc.Input(id='x-plus-y-div-2'), # server-side html.Div([ html.Label('Display x, y, x+y/2 (serverside)'), dcc.Textarea(id='display-all-of-the-values'), ]), # clientside html.Label('Mean(x, y, x+y, x+y/2) (clientside)'), dcc.Input(id='mean-of-all-values'), ]) self.dash.clientside_callback( ClientsideFunction('clientside', 'add'), Output('x-plus-y', 'value'), [Input('x', 'value'), Input('y', 'value')]) self.dash.callback(Output('x-plus-y-div-2', 'value'), [Input('x-plus-y', 'value')])( self.divide_by_two) self.dash.callback( Output('display-all-of-the-values', 'value'), [ Input('x', 'value'), Input('y', 'value'), Input('x-plus-y', 'value'), Input('x-plus-y-div-2', 'value') ])(self.display_all) self.dash.clientside_callback( ClientsideFunction('clientside', 'mean'), Output('mean-of-all-values', 'value'), [ Input('x', 'value'), Input('y', 'value'), Input('x-plus-y', 'value'), Input('x-plus-y-div-2', 'value') ])
def setup_callbacks(app: Dash): @app.callback(Output("nav-list", "children"), [Input('url', 'href')], [State("report-query", "data")], prevent_initial_call=True) def update_nav_links(_, query_string): return generate_nav_links(query_string) # app.clientside_callback( # ClientsideFunction( # namespace="compliance", # function_name="download_pdf" # ), # Output("report-download", "data-download"), # [Input("report-download", "n_clicks")], # prevent_initial_call=True # ) app.clientside_callback( ClientsideFunction( namespace="compliance", function_name="download_png" ), Output("report-download-png", "data-download"), [Input("report-download-png", "n_clicks")], prevent_initial_call=True )
def test_clsd006_no_update(dash_duo): app = Dash(__name__, assets_folder="assets") app.layout = html.Div([ dcc.Input(id="first", value=1), dcc.Input(id="second", value=1), dcc.Input(id="third", value=1) ]) app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="add1_no_update_at_11"), [Output("second", "value"), Output("third", "value")], [Input("first", "value")], [State("second", "value"), State("third", "value")]) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#first", '1') dash_duo.wait_for_text_to_equal("#second", '2') dash_duo.wait_for_text_to_equal("#third", '2') dash_duo.find_element("#first").send_keys("1") dash_duo.wait_for_text_to_equal("#first", '11') dash_duo.wait_for_text_to_equal("#second", '2') dash_duo.wait_for_text_to_equal("#third", '3') dash_duo.find_element("#first").send_keys("1") dash_duo.wait_for_text_to_equal("#first", '111') dash_duo.wait_for_text_to_equal("#second", '3') dash_duo.wait_for_text_to_equal("#third", '4')
def test_clsd001_simple_clientside_serverside_callback(dash_duo): app = Dash(__name__, assets_folder="assets") app.layout = html.Div( [ dcc.Input(id="input"), html.Div(id="output-clientside"), html.Div(id="output-serverside"), ] ) @app.callback(Output("output-serverside", "children"), [Input("input", "value")]) def update_output(value): return 'Server says "{}"'.format(value) app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="display"), Output("output-clientside", "children"), [Input("input", "value")], ) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#output-serverside", 'Server says "None"') dash_duo.wait_for_text_to_equal("#output-clientside", 'Client says "undefined"') dash_duo.find_element("#input").send_keys("hello world") dash_duo.wait_for_text_to_equal("#output-serverside", 'Server says "hello world"') dash_duo.wait_for_text_to_equal("#output-clientside", 'Client says "hello world"')
def test_clsd011_clientside_callback_context_inputs_list(dash_duo): app = Dash(__name__, assets_folder="assets") app.layout = html.Div([ html.Button("btn0", id="btn0"), html.Button("btn1:0", id={"btn1": 0}), html.Button("btn1:1", id={"btn1": 1}), html.Button("btn1:2", id={"btn1": 2}), html.Div(id="output-clientside", style={"font-family": "monospace"}), ]) app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="inputs_list_to_str"), Output("output-clientside", "children"), [Input("btn0", "n_clicks"), Input({"btn1": ALL}, "n_clicks")], ) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal( "#output-clientside", ('[{"id":"btn0","property":"n_clicks"},' '[{"id":{"btn1":0},"property":"n_clicks"},' '{"id":{"btn1":1},"property":"n_clicks"},' '{"id":{"btn1":2},"property":"n_clicks"}]]'), ) dash_duo.find_element("#btn0").click() dash_duo.wait_for_text_to_equal( "#output-clientside", ('[{"id":"btn0","property":"n_clicks","value":1},' '[{"id":{"btn1":0},"property":"n_clicks"},' '{"id":{"btn1":1},"property":"n_clicks"},' '{"id":{"btn1":2},"property":"n_clicks"}]]'), ) dash_duo.find_element("button[id*='btn1\":0']").click() dash_duo.find_element("button[id*='btn1\":0']").click() dash_duo.wait_for_text_to_equal( "#output-clientside", ('[{"id":"btn0","property":"n_clicks","value":1},' '[{"id":{"btn1":0},"property":"n_clicks","value":2},' '{"id":{"btn1":1},"property":"n_clicks"},' '{"id":{"btn1":2},"property":"n_clicks"}]]'), ) dash_duo.find_element("button[id*='btn1\":2']").click() dash_duo.wait_for_text_to_equal( "#output-clientside", ('[{"id":"btn0","property":"n_clicks","value":1},' '[{"id":{"btn1":0},"property":"n_clicks","value":2},' '{"id":{"btn1":1},"property":"n_clicks"},' '{"id":{"btn1":2},"property":"n_clicks","value":1}]]'), )
def test_clsd006_PreventUpdate(dash_duo): app = Dash(__name__, assets_folder="clientside_assets") app.layout = html.Div([ dcc.Input(id="first", value=1), dcc.Input(id="second", value=1), dcc.Input(id="third", value=1), ]) app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="add1_prevent_at_11"), Output("second", "value"), [Input("first", "value")], [State("second", "value")], ) app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="add1_prevent_at_11"), Output("third", "value"), [Input("second", "value")], [State("third", "value")], ) class DashView(BaseDashView): dash = app dash_duo.start_server(DashView) dash_duo.wait_for_text_to_equal("#first", "1") dash_duo.wait_for_text_to_equal("#second", "2") dash_duo.wait_for_text_to_equal("#third", "2") dash_duo.find_element("#first").send_keys("1") dash_duo.wait_for_text_to_equal("#first", "11") dash_duo.wait_for_text_to_equal("#second", "2") dash_duo.wait_for_text_to_equal("#third", "2") dash_duo.find_element("#first").send_keys("1") dash_duo.wait_for_text_to_equal("#first", "111") dash_duo.wait_for_text_to_equal("#second", "3") dash_duo.wait_for_text_to_equal("#third", "3")
def test_clsd003_clientside_exceptions_halt_subsequent_updates(dash_duo): app = Dash(__name__, assets_folder="clientside_assets") app.layout = html.Div([ dcc.Input(id="first", value=1), dcc.Input(id="second"), dcc.Input(id="third") ]) app.clientside_callback( ClientsideFunction("clientside", "add1_break_at_11"), Output("second", "value"), [Input("first", "value")], ) app.clientside_callback( ClientsideFunction("clientside", "add1_break_at_11"), Output("third", "value"), [Input("second", "value")], ) class DashView(BaseDashView): dash = app dash_duo.start_server(DashView) test_cases = [["#first", "1"], ["#second", "2"], ["#third", "3"]] for selector, expected in test_cases: dash_duo.wait_for_text_to_equal(selector, expected) first_input = dash_duo.wait_for_element("#first") first_input.send_keys("1") # clientside code will prevent the update from occurring test_cases = [["#first", "11"], ["#second", "2"], ["#third", "3"]] for selector, expected in test_cases: dash_duo.wait_for_text_to_equal(selector, expected) first_input.send_keys("1") # the previous clientside code error should not be fatal: # subsequent updates should still be able to occur test_cases = [["#first", "111"], ["#second", "112"], ["#third", "113"]] for selector, expected in test_cases: dash_duo.wait_for_text_to_equal(selector, expected)
def __init__(self, **kwargs): super(DashClientsideExceptionsHaltSubsequentUpdates, self).__init__(**kwargs) self.dash.layout = html.Div([ dcc.Input(id='first', value=1), dcc.Input(id='second'), dcc.Input(id='third'), ]) self.dash.clientside_callback( ClientsideFunction('clientside', 'add1_break_at_11'), Output('second', 'value'), [Input('first', 'value')], ) self.dash.clientside_callback( ClientsideFunction('clientside', 'add1_break_at_11'), Output('third', 'value'), [Input('second', 'value')], )
def graph_ui(): plotly_graph = generate_graph_instance(id_="nmr_spectrum") # initialize app with graph instance app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="initialize"), Output("temp1", "children"), [Input("nmr_spectrum", "figure")], ) return dcc.Loading(plotly_graph, type="dot")
def test_clientside_callback_grouping_validation(grouping): """ Clientside callbacks do not support dependency groupings yet, so we make sure that these are not allowed through validation. This test should be removed when grouping support is added for clientside callbacks. """ app = dash.Dash() # Should pass validation with no groupings app.clientside_callback( ClientsideFunction("foo", "bar"), Output("output-a", "prop"), Input("input-a", "prop"), ) # Validation error with output is a grouping with pytest.raises(dash.exceptions.IncorrectTypeException): app.clientside_callback( ClientsideFunction("foo", "bar"), make_dependency_grouping(grouping, [Output]), Input("input-a", "prop"), ) # Validation error with input is a grouping with pytest.raises(dash.exceptions.IncorrectTypeException): app.clientside_callback( ClientsideFunction("foo", "bar"), Output("output-a", "prop"), make_dependency_grouping(grouping, [Input]), ) # Validation error when both are groupings with pytest.raises(dash.exceptions.IncorrectTypeException): app.clientside_callback( ClientsideFunction("foo", "bar"), make_dependency_grouping(grouping, [Output]), make_dependency_grouping(grouping, [Input]), )
def __init__(self, **kwargs): super(DashClientsideFailsWhenReturningAPromise, self).__init__(**kwargs) self.dash.layout = html.Div([ html.Div(id='input', children='hello'), html.Div(id='side-effect'), html.Div(id='output', children='output') ]) self.dash.clientside_callback( ClientsideFunction('clientside', 'side_effect_and_return_a_promise'), Output('output', 'children'), [Input('input', 'children')])
def setup_callbacks(app: dash.Dash, cache: cache_int.CacheInterface) -> None: create_upload_callback(app, "compliance-report", cache) create_upload_callback(app, "training-report", cache) create_button_callback(app, "button", "compliance-report", "training-report", cache) # Show a waiting spinner on clicking the button app.clientside_callback( ClientsideFunction( namespace="compliance", function_name="new_dashboard_spinner" ), Output("button", "data-popup"), [Input("button", "n_clicks")] ) # If components are missing, re-hide the spinner app.clientside_callback( ClientsideFunction( namespace="compliance", function_name="new_dashboard_spinner_hide" ), Output("button", "data-popup-hide"), [Input("button", "children")] )
def test_clsd004_clientside_multiple_outputs(dash_duo): app = Dash(__name__, assets_folder="clientside_assets") app.layout = html.Div([ dcc.Input(id="input", value=1), dcc.Input(id="output-1"), dcc.Input(id="output-2"), dcc.Input(id="output-3"), dcc.Input(id="output-4"), ]) app.clientside_callback( ClientsideFunction("clientside", "add_to_four_outputs"), [ Output("output-1", "value"), Output("output-2", "value"), Output("output-3", "value"), Output("output-4", "value"), ], [Input("input", "value")], ) class DashView(BaseDashView): dash = app dash_duo.start_server(DashView) for selector, expected in [ ["#input", "1"], ["#output-1", "2"], ["#output-2", "3"], ["#output-3", "4"], ["#output-4", "5"], ]: dash_duo.wait_for_text_to_equal(selector, expected) dash_duo.wait_for_element("#input").send_keys("1") for selector, expected in [ ["#input", "11"], ["#output-1", "12"], ["#output-2", "13"], ["#output-3", "14"], ["#output-4", "15"], ]: dash_duo.wait_for_text_to_equal(selector, expected)
def test_clsd009_clientside_callback_context_triggered(dash_duo): app = Dash(__name__, assets_folder="clientside_assets") app.layout = html.Div([ html.Button("btn0", id="btn0"), html.Button("btn1:0", id={"btn1": 0}), html.Button("btn1:1", id={"btn1": 1}), html.Button("btn1:2", id={"btn1": 2}), html.Div(id="output-clientside", style={"font-family": "monospace"}), ]) app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="triggered_to_str"), Output("output-clientside", "children"), [Input("btn0", "n_clicks"), Input({"btn1": ALL}, "n_clicks")], ) class DashView(BaseDashView): dash = app dash_duo.start_server(DashView) dash_duo.wait_for_text_to_equal("#output-clientside", "") dash_duo.find_element("#btn0").click() dash_duo.wait_for_text_to_equal( "#output-clientside", "btn0.n_clicks = 1", ) dash_duo.find_element("button[id*='btn1\":0']").click() dash_duo.find_element("button[id*='btn1\":0']").click() dash_duo.wait_for_text_to_equal("#output-clientside", '{"btn1":0}.n_clicks = 2') dash_duo.find_element("button[id*='btn1\":2']").click() dash_duo.wait_for_text_to_equal( "#output-clientside", '{"btn1":2}.n_clicks = 1', )
def __init__(self, **kwargs): super(DashClientsideMultipleOutputs, self).__init__(**kwargs) self.dash.layout = html.Div([ dcc.Input(id='input', value=1), dcc.Input(id='output-1'), dcc.Input(id='output-2'), dcc.Input(id='output-3'), dcc.Input(id='output-4'), ]) self.dash.clientside_callback( ClientsideFunction('clientside', 'add_to_four_outputs'), [ Output('output-1', 'value'), Output('output-2', 'value'), Output('output-3', 'value'), Output('output-4', 'value') ], [Input('input', 'value')])
def __init__(self, **kwargs): super(DashSimpleClientsideServersideCallback, self).__init__(**kwargs) self.dash.layout = html.Div([ dcc.Input(id='input'), html.Div(id='output-clientside'), html.Div(id='output-serverside') ]) self.dash.callback(Output('output-serverside', 'children'), [Input('input', 'value')])( self.update_output) self.dash.clientside_callback( ClientsideFunction(namespace='clientside', function_name='display'), Output('output-clientside', 'children'), [Input('input', 'value')])
def test_clientside_fails_when_returning_a_promise(self): app = dash.Dash(__name__, assets_folder='clientside_assets') app.layout = html.Div([ html.Div(id='input', children='hello'), html.Div(id='side-effect'), html.Div(id='output', children='output') ]) app.clientside_callback( ClientsideFunction('clientside', 'side_effect_and_return_a_promise'), Output('output', 'children'), [Input('input', 'children')]) self.startServer(app) self.wait_for_text_to_equal('#input', 'hello') self.wait_for_text_to_equal('#side-effect', 'side effect') self.wait_for_text_to_equal('#output', 'output')
def get_local_info_component(app, id, info_component, hidden = True): icon_id = f'{id}_info_icon' button_id = f'{id}_info_button' info_id = f'{id}_info' info_button = get_info_button(icon_id, button_id, hidden) info_section = html.P([info_component], id=info_id) app.clientside_callback( ClientsideFunction( namespace='clientside', function_name='display_info' ), [Output(info_id, 'style'), Output(icon_id, 'className')], [Input(button_id, 'n_clicks')] ) return info_button, info_section
def test_clsd005_clientside_fails_when_returning_a_promise(dash_duo): app = Dash(__name__, assets_folder="assets") app.layout = html.Div([ html.Div(id="input", children="hello"), html.Div(id="side-effect"), html.Div(id="output", children="output"), ]) app.clientside_callback( ClientsideFunction("clientside", "side_effect_and_return_a_promise"), Output("output", "children"), [Input("input", "children")], ) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#input", "hello") dash_duo.wait_for_text_to_equal("#side-effect", "side effect") dash_duo.wait_for_text_to_equal("#output", "output")
def test_clientside_multiple_outputs(self): app = dash.Dash(__name__, assets_folder='clientside_assets') app.layout = html.Div([ dcc.Input(id='input', value=1), dcc.Input(id='output-1'), dcc.Input(id='output-2'), dcc.Input(id='output-3'), dcc.Input(id='output-4'), ]) app.clientside_callback( ClientsideFunction('clientside', 'add_to_four_outputs'), [Output('output-1', 'value'), Output('output-2', 'value'), Output('output-3', 'value'), Output('output-4', 'value')], [Input('input', 'value')]) self.startServer(app) for test_case in [ ['#input', '1'], ['#output-1', '2'], ['#output-2', '3'], ['#output-3', '4'], ['#output-4', '5'] ]: self.wait_for_text_to_equal(test_case[0], test_case[1]) input = self.wait_for_element_by_css_selector('#input') input.send_keys('1') for test_case in [ ['#input', '11'], ['#output-1', '12'], ['#output-2', '13'], ['#output-3', '14'], ['#output-4', '15'] ]: self.wait_for_text_to_equal(test_case[0], test_case[1])
def test_simple_clientside_serverside_callback(self): app = dash.Dash(__name__, assets_folder='clientside_assets') app.layout = html.Div([ dcc.Input(id='input'), html.Div(id='output-clientside'), html.Div(id='output-serverside') ]) @app.callback( Output('output-serverside', 'children'), [Input('input', 'value')]) def update_output(value): return 'Server says "{}"'.format(value) app.clientside_callback( ClientsideFunction( namespace='clientside', function_name='display' ), Output('output-clientside', 'children'), [Input('input', 'value')] ) self.startServer(app) input = self.wait_for_element_by_css_selector('#input') self.wait_for_text_to_equal('#output-serverside', 'Server says "None"') self.wait_for_text_to_equal( '#output-clientside', 'Client says "undefined"' ) input.send_keys('hello world') self.wait_for_text_to_equal( '#output-serverside', 'Server says "hello world"' ) self.wait_for_text_to_equal( '#output-clientside', 'Client says "hello world"' )
def download_session_ui(): """Download session""" session_link = html.A(id="download-session-link", style={"display": "none"}) session_button = custom_button( icon_classname="fas fa-file-download fa-lg", tooltip="Click to download the session", id="download-session-button", className="icon-button", module="html", ) # callback for downloading session app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="downloadSession"), Output("download-session-link", "href"), Input("download-session-button", "n_clicks"), State("local-simulator-data", "data"), prevent_initial_call=True, ) return html.Div([session_link, session_button])
def test_extg007_clientside(dash_duo): app = dash.Dash(__name__) initial_graph_title = "initial title" header = html.Div( id="header", children=[html.Button(id="update-title", children=["Update Title"])], ) graph = html.Div( children=[ deg.ExtendableGraph( id="deg-clientside-test", figure=dict( layout=dict(title=initial_graph_title), data=[ dict(x=[1, 2, 3, 4], y=[5, 4, 3, 6], line=dict(shape="spline"),) ], ), ) ], ) app.clientside_callback( ClientsideFunction("pytest", "relayout"), Output("header", "style"), [Input("update-title", "n_clicks")], [State("deg-clientside-test", "figure")], ) app.layout = html.Div([header, graph]) dash_duo.start_server(app) dash_duo.wait_for_contains_text("#deg-clientside-test", initial_graph_title) dash_duo.wait_for_element("#update-title").click() dash_duo.wait_for_contains_text( "#deg-clientside-test", "{}-new".format(initial_graph_title) )
def test_clsd013_clientside_callback_context_states_list(dash_duo): app = Dash(__name__, assets_folder="assets") app.layout = html.Div( [ dcc.Input(id="in0"), dcc.Input(id={"in1": 0}), dcc.Input(id={"in1": 1}), dcc.Input(id={"in1": 2}), html.Div(id="output-clientside", style={"font-family": "monospace"}), ] ) app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="states_list_to_str"), Output("output-clientside", "children"), [Input("in0", "n_submit"), Input({"in1": ALL}, "n_submit")], [State("in0", "value"), State({"in1": ALL}, "value")], ) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal( "#output-clientside", ( '[{"id":"in0","property":"value"},' '[{"id":{"in1":0},"property":"value"},' '{"id":{"in1":1},"property":"value"},' '{"id":{"in1":2},"property":"value"}]]' ), ) dash_duo.find_element("#in0").send_keys("test 0" + Keys.RETURN) dash_duo.wait_for_text_to_equal( "#output-clientside", ( '[{"id":"in0","property":"value","value":"test 0"},' '[{"id":{"in1":0},"property":"value"},' '{"id":{"in1":1},"property":"value"},' '{"id":{"in1":2},"property":"value"}]]' ), ) dash_duo.find_element("input[id*='in1\":0']").send_keys("test 1" + Keys.RETURN) dash_duo.wait_for_text_to_equal( "#output-clientside", ( '[{"id":"in0","property":"value","value":"test 0"},' '[{"id":{"in1":0},"property":"value","value":"test 1"},' '{"id":{"in1":1},"property":"value"},' '{"id":{"in1":2},"property":"value"}]]' ), ) dash_duo.find_element("input[id*='in1\":2']").send_keys("test 2" + Keys.RETURN) dash_duo.wait_for_text_to_equal( "#output-clientside", ( '[{"id":"in0","property":"value","value":"test 0"},' '[{"id":{"in1":0},"property":"value","value":"test 1"},' '{"id":{"in1":1},"property":"value"},' '{"id":{"in1":2},"property":"value","value":"test 2"}]]' ), )
def test_clsd002_chained_serverside_clientside_callbacks(dash_duo): app = Dash(__name__, assets_folder="assets") app.layout = html.Div( [ html.Label("x"), dcc.Input(id="x", value=3), html.Label("y"), dcc.Input(id="y", value=6), # clientside html.Label("x + y (clientside)"), dcc.Input(id="x-plus-y"), # server-side html.Label("x+y / 2 (serverside)"), dcc.Input(id="x-plus-y-div-2"), # server-side html.Div( [ html.Label("Display x, y, x+y/2 (serverside)"), dcc.Textarea(id="display-all-of-the-values"), ] ), # clientside html.Label("Mean(x, y, x+y, x+y/2) (clientside)"), dcc.Input(id="mean-of-all-values"), ] ) app.clientside_callback( ClientsideFunction("clientside", "add"), Output("x-plus-y", "value"), [Input("x", "value"), Input("y", "value")], ) call_counts = {"divide": Value("i", 0), "display": Value("i", 0)} @app.callback(Output("x-plus-y-div-2", "value"), [Input("x-plus-y", "value")]) def divide_by_two(value): call_counts["divide"].value += 1 return float(value) / 2.0 @app.callback( Output("display-all-of-the-values", "value"), [ Input("x", "value"), Input("y", "value"), Input("x-plus-y", "value"), Input("x-plus-y-div-2", "value"), ], ) def display_all(*args): call_counts["display"].value += 1 return "\n".join([str(a) for a in args]) app.clientside_callback( ClientsideFunction("clientside", "mean"), Output("mean-of-all-values", "value"), [ Input("x", "value"), Input("y", "value"), Input("x-plus-y", "value"), Input("x-plus-y-div-2", "value"), ], ) dash_duo.start_server(app) test_cases = [ ["#x", "3"], ["#y", "6"], ["#x-plus-y", "9"], ["#x-plus-y-div-2", "4.5"], ["#display-all-of-the-values", "3\n6\n9\n4.5"], ["#mean-of-all-values", str((3 + 6 + 9 + 4.5) / 4.0)], ] for selector, expected in test_cases: dash_duo.wait_for_text_to_equal(selector, expected) assert call_counts["display"].value == 1 assert call_counts["divide"].value == 1 x_input = dash_duo.wait_for_element_by_css_selector("#x") x_input.send_keys("1") test_cases = [ ["#x", "31"], ["#y", "6"], ["#x-plus-y", "37"], ["#x-plus-y-div-2", "18.5"], ["#display-all-of-the-values", "31\n6\n37\n18.5"], ["#mean-of-all-values", str((31 + 6 + 37 + 18.5) / 4.0)], ] for selector, expected in test_cases: dash_duo.wait_for_text_to_equal(selector, expected) assert call_counts["display"].value == 2 assert call_counts["divide"].value == 2
reset = False # Find which one has been triggered ctx = dash.callback_context if ctx.triggered: prop_id = ctx.triggered[0]["prop_id"].split(".")[0] if prop_id == "reset-btn": reset = True # Return to original hm(no colored annotation) by resetting return generate_patient_volume_heatmap(start, end, clinic, hm_click, admit_type, reset) app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="resize"), Output("output-clientside", "children"), [Input("wait_time_table", "children")] + wait_time_inputs + score_inputs, ) @app.callback( Output("wait_time_table", "children"), [ Input("date-picker-select", "start_date"), Input("date-picker-select", "end_date"), Input("clinic-select", "value"), Input("admit-select", "value"), Input("patient_volume_hm", "clickData"), Input("reset-btn", "n_clicks"), ] + wait_time_inputs + score_inputs,
def test_clsd012_clientside_callback_context_states(dash_duo): app = Dash(__name__, assets_folder="clientside_assets") app.layout = html.Div([ dcc.Input(id="in0"), dcc.Input(id={"in1": 0}), dcc.Input(id={"in1": 1}), dcc.Input(id={"in1": 2}), html.Div(id="output-clientside", style={"font-family": "monospace"}), ]) app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="states_to_str"), Output("output-clientside", "children"), [Input("in0", "n_submit"), Input({"in1": ALL}, "n_submit")], [State("in0", "value"), State({"in1": ALL}, "value")], ) class DashView(BaseDashView): dash = app dash_duo.start_server(DashView) dash_duo.wait_for_text_to_equal( "#output-clientside", ("in0.value = null, " '{"in1":0}.value = null, ' '{"in1":1}.value = null, ' '{"in1":2}.value = null'), ) dash_duo.find_element("#in0").send_keys("test 0" + Keys.RETURN) dash_duo.wait_for_text_to_equal( "#output-clientside", ("in0.value = test 0, " '{"in1":0}.value = null, ' '{"in1":1}.value = null, ' '{"in1":2}.value = null'), ) dash_duo.find_element("input[id*='in1\":0']").send_keys("test 1" + Keys.RETURN) dash_duo.wait_for_text_to_equal( "#output-clientside", ("in0.value = test 0, " '{"in1":0}.value = test 1, ' '{"in1":1}.value = null, ' '{"in1":2}.value = null'), ) dash_duo.find_element("input[id*='in1\":2']").send_keys("test 2" + Keys.RETURN) dash_duo.wait_for_text_to_equal( "#output-clientside", ("in0.value = test 0, " '{"in1":0}.value = test 1, ' '{"in1":1}.value = null, ' '{"in1":2}.value = test 2'), )
], className="pure-u-1 pure-u-lg-1-2 pure-u-xl-4-24"), html.Div([ html.Div([dcc.Markdown(intro_md)], className="text-block") ], className="pure-u-1 pure-u-lg-1 pure-u-xl-22-24"), ], className="pure-g"), ], ) # ---------------------- Callbacks --------------------------------- # Callbacks are all client-side (https://dash.plot.ly/performance) # in order to transform the app into static html pages # javascript functions are defined in assets/callbacks.js app.clientside_callback(ClientsideFunction(namespace='clientside2', function_name='get_store_data'), output=Output('plot', 'figure'), inputs=[Input('store', 'data')]) app.clientside_callback( ClientsideFunction(namespace='clientside', function_name='update_store_data'), output=Output('store', 'data'), inputs=[Input('table', "data"), Input('table', "selected_rows")], state=[State('store', 'data')], ) app.clientside_callback( ClientsideFunction(namespace='clientside3', function_name='update_table'), output=Output('table', 'selected_rows'),