Black Lives Matter. Please consider donating to Black Girls Code today.

Dash RangeSlider visual bug when updating

Hello, As the title suggests I’m having trouble with updating a range slider without getting a strange visual error. I have an application that allows the user to select a date, after selecting the date information is pulled from a database for that day and the range slider min is set to the earliest recorded time for that day) and the max is set to the latest recorded time, then finally the value is set to be from the min to the max. When a date is first selected the slider is fine. However if another date is selected and the earliest time for this day is earlier than the previous selection then the slider goes across the entire screen.

I am not sure how to fix this or if anyone has experienced this before, but any advice on how to prevent this would be appreciated. I will post the code for how the slider is built below but please let me know if you need any more information from me

@app.callback(
    Output('slider-containter', 'children'),
    [Input('data-store', 'data')])
def make_slider(data):
    if data is None:
      raise PreventUpdate
    timestamps = data['timestamps']
    start_time = min(timestamps)
    end_time = max(timestamps)
    return dcc.RangeSlider(
                id='time-slider',
                min = start_time,
                max = end_time,
                allowCross=False,
                value = [start_time, end_time])

Thank you and have a wonderful day!

Edit:
Here is some code recreating the issue:

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
from datetime import datetime

# Dash stylesheet setup
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config['suppress_callback_exceptions']=True

app.layout = html.Div(children=[
    html.H1(children='Dash App'),
    html.Div(className='row', children=[
        html.Div(
            dcc.Dropdown
                (
                id='uid-select',
                options=[{'label': 'A', 'value': 'A'}],
                searchable=True,
                clearable=False,
            ),
            className='two columns'),
        html.Div(
            dcc.Dropdown
                (
                id='date-select',
                searchable=True,
                clearable=False,
            ),
            className='two columns'),
        html.Div(id='slider-containter', className='six columns'),
        dcc.Store(id='data-store')
    ])
])


@app.callback(
        Output('date-select', 'options'),
        [Input('uid-select', 'value')])
def update_date_dropdown(uid):
    if uid is None:
        raise PreventUpdate
    dates = []
    if uid is 'A':
        dates.append("04-16-2019")
        dates.append("04-17-2019")
    return [{'label': i,
             'value': datetime.strptime(i, '%m-%d-%Y').timestamp()
            } for i in dates]

'''
    This callback does not accurately reflect its true purpose in the
    full program. In the full code it involves a query based off a specific
    identifier provided by the first dropdown, but here it should suffice 
    to say that this callback simply collects data including the time range 
    used to create the slider.
'''
@app.callback(
    Output('data-store', 'data'),
    [Input('date-select', 'value')])
def get_data(timestamp):
    if timestamp is None:
        raise PreventUpdate
    timestamps = []
    some_data = []
    some_more_data = []
    even_more_data =  []
    if timestamp == 1555387200:
        timestamps.append(1555438040)
        timestamps.append(1555442908)
    if timestamp == 1555473600:
        timestamps.append(1555497676)
        timestamps.append(1555531820)
    some_data.append("some data")
    some_more_data.append("some more data")
    even_more_data.append("even more data")

    return {'some_data': some_data,
            'some_more_data': some_more_data,
            'even_more_data': even_more_data,
            'timestamps': timestamps}

@app.callback(
    Output('slider-containter', 'children'),
    [Input('data-store', 'data')])
def make_slider(data):
    if data is None:
        raise PreventUpdate
    timestamps = data['timestamps']
    start_time = min(timestamps)
    end_time = max(timestamps)
    return dcc.RangeSlider(
                id='time-slider',
                min = start_time,
                max = end_time,
                allowCross=False,
                value = [start_time, end_time])

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

Can you post the entire app.py file so attempting to reproduce is easier?

Unfortunately the entire code contains confidential information about the company I work for (DB connections and all that) so I cannot post everything.

Ok…maybe a standalone/filtered app.py that reproduces the problem, as your callback looks ok.

I am working on a small script that may be able to reproduce the problem.

Have you checked out the app using the react Dev tool inspector? I find that to be a useful resource when the error is not an obvious python runtime error.

Also, another hunch I had was that maybe there are mixed types or NaN values in your timestamp column.

I have not used that inspector tool you spoke of, but I can say for sure there are no NaN values in the timestamp column.

The example code has been added.

The problem appears to be the values assoc. with your rangeslider. You are setting the value, min and max to be unix timestamps. While the online docs indicate these are valid (i.e you are providing proper values), it appears dcc.RangeSlider doesn’t handle this very well. If you set the values between 0 and len(timestamps), you can set the marks to be the actual timestamps.

Prob. not ideal but it’s the only way I could get your code to work w/o the visualization bug you reported.

I would recommend filing a bug report w/ the sample code you provided.

Thank you for having a look! I am very new to Dash and Plotly, so I don’t know where or how to file a bug report. Would you happen to know?

From https://dash.plot.ly/, click on Dash Installation. This takes you to the page that also shows the change logs for various projects.

For dcc, the direct link is https://github.com/plotly/dash-core-components/blob/master/CHANGELOG.md

You may also be interested in dash-bootstrap-components for an alternate way to style your app. I transitioned my app w/ minimal headache. See https://dash-bootstrap-components.opensource.faculty.ai/.

Good luck w/ you app dev!

1 Like

I work a lot with RangeSlider.
I may suggest you to use static data, tune your dev to solve the visual bug (if there’s any) and then use runtime data.
You can’t share dev because of confidential, but you can share static dummy data that shows the visual…