Dash range slider which able to interact with input field that display range slider value

Hi guys,
I’m new to dash and for a dashboard I work on for a project there need to be a range slider and 2 input boxes that interact with each other.
Basically 2 requirements are;

  • start and end values of range slider should be displayed in the input boxes, and update whenever i move the slider
  • If I enter values in input boxes slider points have to be updated accordingly

I have included the basic code I’m working on now.

import dash
import dash_html_components as html
import dash_core_components as dcc

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

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
    html.Div([
        dcc.Input(id='start_value', type='text')
    ], id='start_value_div'),
    dcc.RangeSlider(
        id='my-range-slider',
        min=0,
        max=20,
        step=0.5,
        value=[5, 15]
    ),
    html.Div([
        dcc.Input(id='end_value', type='text')
    ], id='end_value_div')


])

# Display start value of range in input field
@app.callback(
    dash.dependencies.Output('start_value_div', 'children'),
    [dash.dependencies.Input('my-range-slider', 'value')])
def update_output(value):
    return value[0]

# Display end value of range in input field
@app.callback(
    dash.dependencies.Output('end_value_div', 'children'),
    [dash.dependencies.Input('my-range-slider', 'value')])
def update_output(value):
    return value[1]

# Display start & end value of input fields in range slider if user enters values
@app.callback(
    dash.dependencies.Output('my-range-slider', 'value'),
    [dash.dependencies.Input('start_value_div', 'children'),
    dash.dependencies.Input('end_value_div', 'children')])
def update_output(start_value, end_value):
    value = [start_value, end_value]
    return value



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

What I currently get is a text area instead of input box and they don’t interact with the slider the way I want.


Is this possible in dash? Please help me with this

Hi @wide93

If you want to update the dcc.Input you need to set that Input id as Output in the callback, you are setting the html.Div id instead.

You can’t update the Input from the range slider and at the same time update the range slider with those input because is a circular reference. There exist a way but is a litle bit complicate (putting all together in the same callback and finding wich option was triggered), but I think is better to think for other layout.

@Eduardo was correct, but with today’s announcement of the latest release it is now possible to have some circular callbacks which enables you to make synchronized components :confetti_ball:

Be sure to upgrade to dash 1.19.0, then this example will work:

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html

external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div(
    [
        html.H4("Synchronized Components"),
        dcc.RangeSlider(
            id="slider",
            min=0,
            max=20,
            marks={i: str(i) for i in range(21)},
            value=[5, 15],
        ),
        "Start Value:",
        dcc.Input(id="start_value", type="number", min=0, max=20, value=5),
        "End Value:",
        dcc.Input(id="end_value", type="number", min=0, max=20, value=15),
    ]
)


@app.callback(
    Output("start_value", "value"),
    Output("end_value", "value"),
    Output("slider", "value"),
    Input("start_value", "value"),
    Input("end_value", "value"),
    Input("slider", "value"),
)
def callback(start, end, slider):
    ctx = dash.callback_context
    trigger_id = ctx.triggered[0]["prop_id"].split(".")[0]

    start_value = start if trigger_id == "start_value" else slider[0]
    end_value = end if trigger_id == "end_value" else slider[1]
    slider_value = slider if trigger_id == "slider" else [start_value, end_value]

    return start_value, end_value, slider_value


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

range_slider_sync

2 Likes

Hey. Thanks you for the answer. You were right about the html.Div. Changing it to input id solved the issue.

Regarding the updating input from range slider, I was able to introduce a submit button to the input boxes, take the values as state rather than input and avoid the circular reference. Although this is not the most ideal solution it works for the time being.

1 Like