plotly / dash

Data Apps & Dashboards for Python. No JavaScript Required.

Home Page:https://plotly.com/dash

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[BUG] width of the dcc.Input field does not scale properly when step=None

nadijagraca opened this issue · comments

Describe your context

My environment:

dash                 2.15.0
dash-core-components 2.0.0
dash-html-components 2.0.0
dash-table           5.0.0

Describe the bug

I have a dcc.Input component linked to the dcc.Slider, the components share min, max, step and value properties. When I set step=None, and drag the slider handle to some value with decimal places, the decimal numbers are sometimes cut-off.
Example screenshot below. (notice missing number after the comma)

Screenshot 2024-03-12 at 16 41 23

Upon further investigation I found that this happens when step is set to None, and number of digits in the value exceeds the number of digits of the max property. In the example from the screenshot above I had max=2007 and step=None.

Once I set step to be 0.5, the width of the input field scaled and displayed the number correctly.

Screenshot 2024-03-12 at 16 39 46

Expected behavior
Since step was set to None, slider automatically calculated the step size of 0.5, but it did not take it into account when scaling the width of the input field. Ideally, the automatically calculated step size should be taken into account when scaling the width of the input field, in the same way as it is done when users explicitly set step size.

Screenshots

If applicable, add screenshots or screen recording to help explain your problem.

commented

HI @nadijagraca
Thank you for reporting this. Can you please share a minimal reproducible example code so we can replicated this bug locally?

Hi Adam,
Apologies for not including it.

Below you can find example code. If you replace step=None with step=0.5 the number in the input field is displayed correctly.

from dash import Dash, Input, Output, callback, dcc, html

app = Dash(__name__)

app.layout = html.Div(
    [
        dcc.Input(id="input-slider", type="number", min=1957, max=2007, step=None, value=1990),
        dcc.Slider(
             id="slider", min=1957, max=2007, marks=None, value=1990, dots=False, step=None, updatemode="drag"
        ),
    ]
)


@callback(Output("input-slider", "value"), Input("slider", "value"))
def update_output(value):
    return value


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

Screenshot 2024-03-13 at 11 56 37

To replicate the bug you will need to use slider handle, and once the slider handle is dragged to the number with decimal place, you will notice that the decimal place is being cut-off from the input field.

commented

hi @nadijagraca
Thanks for sharing the code. For some reason, I'm not able to reproduce the error. I ran your code as step=None and step=0.5, and in bot cases the complete number/float is visible.

I'm using Dash 2.16.1 on a Windows 11. And it worked fine on Firefox, Edge, and Brave.
Can you try Dash 2.16.1? What OS are you using?

slider1

@Coding-with-Adam @nadijagraca I am seeing the issue on Mac in Safari and Chrome. No issue in Firefox because the box is wider overall in Firefox. I wonder what is causing the width difference between browsers.

With step=None on the dcc.Input:
Screen Shot 2024-03-21 at 11 57 15 AM
Screen Shot 2024-03-21 at 11 57 29 AM

With step=0.5:
Screen Shot 2024-03-21 at 4 47 21 PM

Odd that the width of the box is affected by the value of step!

Worth noting, though, that setting step=None isn't really valid according to the docs — the default value for step is "any". Setting step="any", or not passing a value for step at all, gives a wider box, even in Safari/Chrome:
Screen Shot 2024-03-21 at 5 00 09 PM

If I were to guess I would say dcc.Input is doing some fancy logic to try to guess the minimum length needed for the input box, but is not handling the null value correctly.

After another look I see that dcc.Input is a pretty light wrapper around the HTML <input> component, and the logic around choosing the box width is implemented by the browser, based on the min, max and step values. Which explains why the behavior is different across browsers.

So the answer here I think is

  1. set step="any" (or don't pass a value for step, meaning the default of "any" will be used) to nudge the browser to use the 'default' input field width which is around 20 characters, OR
  2. use CSS to set a different, custom, width if needed
commented

Thank you for the solution, @emilykl