Skip to content

Instantly share code, notes, and snippets.

@jtpio
Created January 24, 2018 23:17
Show Gist options
  • Save jtpio/1aeb0d850dcd537a5b244bcf5aeaa75b to your computer and use it in GitHub Desktop.
Save jtpio/1aeb0d850dcd537a5b244bcf5aeaa75b to your computer and use it in GitHub Desktop.
Dash URL State example
import dash
import dash_core_components as dcc
import dash_html_components as html
from urllib.parse import urlparse, parse_qsl, urlencode
from dash.dependencies import Input, Output
app = dash.Dash()
app.config.suppress_callback_exceptions = True
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='page-layout')
])
def apply_default_value(params):
def wrapper(func):
def apply_value(*args, **kwargs):
if 'id' in kwargs and kwargs['id'] in params:
kwargs['value'] = params[kwargs['id']]
return func(*args, **kwargs)
return apply_value
return wrapper
def build_layout(params):
layout = [
html.H2('URL State demo', id='state'),
apply_default_value(params)(dcc.Dropdown)(
id='dropdown',
options=[{'label': i, 'value': i} for i in ['LA', 'NYC', 'MTL']],
value='LA'
),
apply_default_value(params)(dcc.Input)(
id='input',
placeholder='Enter a value...',
value=''
),
apply_default_value(params)(dcc.Slider)(
id='slider',
min=0,
max=9,
marks={i: 'Label {}'.format(i) for i in range(10)},
value=5,
),
html.Br(),
]
return layout
def parse_state(url):
parse_result = urlparse(url)
params = parse_qsl(parse_result.query)
state = dict(params)
return state
@app.callback(Output('page-layout', 'children'),
inputs=[Input('url', 'href')])
def page_load(href):
if not href:
return []
state = parse_state(href)
return build_layout(state)
component_ids = [
'dropdown',
'input',
'slider'
]
@app.callback(Output('url', 'search'),
inputs=[Input(i, 'value') for i in component_ids])
def update_url_state(*values):
state = urlencode(dict(zip(component_ids, values)))
return f'?{state}'
if __name__ == '__main__':
app.run_server(debug=True)
dash==0.20.0
dash-renderer==0.11.2
dash-html-components==0.8.0
dash-core-components==0.18.0
@eddy-geek
Copy link

eddy-geek commented Mar 22, 2020

The original gist does not work anymore with the stricter type enforcement of recent Dash:

The low-footprint fix I tried is to try to coerce the vale into its existing type (won't work if it's init with None):

def apply_default_value(params):
    def wrapper(func):
        def apply_value(*args, **kwargs):
            if 'id' in kwargs and kwargs['id'] in params:
                hval = kwargs['value']  # hardcoded value
                sval = params[kwargs['id']]  # saved value
                ctor = None if hval is None or isinstance(hval, str) else type(hval)
                kwargs['value'] = ctor(sval) if ctor else sval
            return func(*args, **kwargs)
        return apply_value
    return wrapper

It works but it's brittle (so I moved to another approach: plotly/dash#188 (comment) )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment