How to turn boolean switch on for designated period of time

Hi Everybody,

I’m trying to incorporate a boolean switch from the dash-daq library and I would like to be able to turn the switch on manually, but then have it turn off automatically after a certain number of seconds. I think this should be possible, but I don’t really understand how to do this. I tried creating a callback to click a button after the switch gets turned on and then setting another callback to trigger on the button click, but that didn’t seem to work. Here is what I tried so far:

import dash
import dash_daq as daq
import dash_html_components as html
from dash.dependencies import Input, Output
import time

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([
    daq.BooleanSwitch(
        id='my-boolean-switch',
        on=False
    ),
    html.Div(id='boolean-switch-output'),
    html.Button(id='button',n_clicks=0,style={'display': 'none'}) #hidden button to add timer functionality
])


@app.callback(
    [Output('boolean-switch-output', 'children'),
     Output('button','n_clicks')],
    [Input('my-boolean-switch', 'on')])
def update_output(on):
    if on:
        n=1
    else:
        n=0
    output_string = 'The switch is {}.'.format(on)
    return (output_string,n)

@app.callback(
    Output('my-boolean-switch', 'on'),
    [Input('button','n_clicks')]
)
def boolean_switch_timer(n):
    if n==1:
        time.sleep(10)
        return False
    else:
        raise dash.exceptions.PreventUpdate

if __name__ == '__main__':
    app.run_server(debug=True)

This is the exception error that I got:

:rescue_worker_helmet:Circular Dependencies3:17:06 PM

Error: Dependency Cycle Found: my-boolean-switch.on → button.n_clicks → my-boolean-switch.on

I think I understand why I’m seeing this circular dependency error, but I don’t really know how else to accomplish the timer functionality. If somebody has an idea, I’d really appreciate any suggestions. Thanks in advance for your help!

Ben

Hello,
I’m not an expert but maybe you can use dcc.Interval() which fire a callback periodically.
Here’s the doc -> https://dash.plotly.com/dash-core-components/interval

Hi @bens44, to circumvent the circular dependency issue you can return the whole Boolean switch object as part of the second callback instead of updating its status.
You would typically do this by setting the children attribute of the parent component. You may need to add a Div wrapping your Boolean switch so that you only need to return the switch component in the callback.

Hi @RenaudLN. Thank you so much for your reply! I’m not exactly sure if I did what you meant, but either way I got it to work. I really appreciate it! Here is the code in case if somebody needs to reference it:

import dash
import dash_daq as daq
import dash_html_components as html
from dash.dependencies import Input, Output
import time

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([
    html.Div(id='container', children = daq.BooleanSwitch(
        id='my-boolean-switch',
        on=False
    )),
    html.Div(id='boolean-switch-output'),
    html.Button(id='button',n_clicks=0,style={'display': 'none'})
])


@app.callback(
    [Output('boolean-switch-output', 'children'),
     Output('button','n_clicks')],
    [Input('my-boolean-switch', 'on')])
def update_output(on):
    if on:
        n=1
    else:
        n=0
    output_string = 'The switch is {}.'.format(on)
    return (output_string,n)

@app.callback(
    Output('container','children'),
    [Input('button','n_clicks')]
)
def boolean_switch_timer(n):
    try:
        if n==1:
            time.sleep(10)
            return daq.BooleanSwitch(id='my-boolean-switch', on=False)
        elif n==0:
            return daq.BooleanSwitch(id='my-boolean-switch', on=False)
        else:
            raise dash.exceptions.PreventUpdate
    except:
        raise dash.exceptions.PreventUpdate

if __name__ == '__main__':
    app.run_server(debug=True)

Thanks again!!

Yep that was exactly it :slight_smile: glad it worked.