plotly / dash

Data Apps & Dashboards for Python. No JavaScript Required.
https://plotly.com/dash
MIT License
21.5k stars 2.07k forks source link

dcc.Dropdown reopens when switching back from another window #1934

Open emilykl opened 2 years ago

emilykl commented 2 years ago

Describe your context

dash                 2.1.0
dash-core-components 2.0.0
dash-html-components 2.0.0
dash-table           5.0.0
- OS: Mac OS
- Browser: Safari (14.0), Chrome (97.0), Firefox (93.0)

Describe the bug

Steps to reproduce:

  1. Select an item in a dcc.Dropdown
  2. While the dropdown still has focus (blue halo), switch to a different tab or window, then switch back to the first window
  3. The dcc.Dropdown menu will reopen

Expected behavior

The dropdown menu does not reopen when switching back to the window

Screenshots

https://user-images.githubusercontent.com/4672118/154557082-3633d611-e520-4745-8aff-3e80b4ebd7c1.mov

Minimal example

(it's just an app with a dropdown)

import dash
from dash import dcc, html

app = dash.Dash(__name__)
server = app.server

def layout():
    return html.Div(
        children=dcc.Dropdown(
            options=[
                "New York City",
                "Montreal",
                "San Francisco",
            ],
            value="Montreal",
        ),
        style={"padding": "10px"},
    )

app.layout = layout()

if __name__ == "__main__":
    app.run_server(debug=True)
celia-lm commented 5 months ago

Updated workaround:

from dash import Dash, callback, clientside_callback, Input, Output, State, dcc, html, ctx

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

import base64
import datetime
import io

import pandas as pd

app = Dash(__name__)

app.layout = html.Div([
    dcc.Dropdown(options=['AB', 'CCD', 'EF', 'G'], id='drop'),
    html.Div(id='dummy'),
    # optional, for demo purposes
    html.Div('I will be updated when the dropdown value changes!', id='out')
])

clientside_callback(
    """
function (val, dropdown_id) {
    document.getElementById(dropdown_id).querySelector('input').blur();
    return [];
    }
    """,
    Output('dummy', 'children'),
    Input('drop', 'value'),
    State('drop', 'id'),
    prevent_initial_call=True
)

# optional, for demo purposes
@callback(
    Output('out', 'children'),
    Input('drop', 'value'),
    prevent_initial_call=True
)
def cbtest(value):
    return f"Value is {value}"

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