plotly / plotly/dash

Pattern-Matching Callbacks ALL have inconsistent order in dash 2.18.1

Open
#3,063 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug P2
Dominant language
Python
Stars
24.4k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
13

Description

dash==2.18.1
dash-core-components==2.0.0
dash-html-components==2.0.0
dash-bootstrap-components==1.6.0

BUG reappear in some circumstances | dash 2.18.1

Image

code :

from dash import Dash, dcc, html
from dash import callback, ALL
from dash.dependencies import Input, Output, State
import dash_bootstrap_components as dbc

ip = "localhost"
port = "8848"

processes = ["optimize", "resize", "upscale"]

videoSizesDict = [
    {"label":"480p/SD", "width":854, "height":480},
    {"label":"720p/HD", "width":1280, "height":720},
    {"label":"1080p/FHD", "width":1920, "height":1080},
    {"label":"1440p/2K", "width":2560, "height":1440},
    {"label":"2160p/4K", "width":3840, "height":2160},
    {"label":"4320p/8K", "width":7680, "height":4320},
]

upscaleFactor = [2, 3, 4]

app = Dash(__name__)

app.layout = html.Div([
    dcc.Dropdown(
        processes,
        value=processes[0],
        id="dropdown_processes",
        style={"color": "black"},
    ),
    html.Div(id="div_processParamUI"),
    html.Div(id="text"),
])

def qualityInputUI():
    return [
        html.Div("Div"),
        dcc.Input(
            id={"type": "input", "id": "videoQuality"},
            type="number",
            value=3.0,
        ),
    ]

def sizeInputUI():
    global videoSizesDict
    return [
        html.Div("Div"),
        dbc.Row(
            [
                dbc.Col(
                    dcc.Input(
                        id={"type": "input", "id": "videoWidth"},
                        type="number",
                        value=1920,
                    ),
                    width=3,
                ),
                dbc.Col(
                    html.Button(
                        "X",
                        id="button_sizeSwitch",
                        n_clicks=0,
                    ),
                    width=1,
                ),
                dbc.Col(
                    dcc.Input(
                        id={"type": "input", "id": "videoHeight"},
                        type="number",
                        value=1080,
                    ),
                    width=3,
                ),
                dbc.Col(
                    dcc.Dropdown(
                        [videoSizes["label"] for videoSizes in videoSizesDict],
                        value=[videoSizes["label"] for videoSizes in videoSizesDict][2],
                        id="dropdown_videoSize",
                    ),
                    width=5,
                ),
            ],
            className="g-0",
        ),
    ]

def upscaleInputUI():
    global upscaleFactor
    return [
        html.Div("Div"),
        dcc.Dropdown(
            upscaleFactor,
            upscaleFactor[0],
            id={"type": "input", "id": "upscaleFactor"},
        ),
    ]

@callback(
    Output('div_processParamUI', 'children'),
    Input('dropdown_processes', 'value'),
)
def update_div_processParamUI(selectedProcess):
    if selectedProcess == "optimize":
        return [
            html.H6("H6"),
            *qualityInputUI(),
        ]
    elif selectedProcess == "resize":
        return [
            html.H6("H6"), # comment this line to remove the bug
            *sizeInputUI(),
            *qualityInputUI(),
        ]
    elif selectedProcess == "upscale":
        return [
            html.H6("H6"), # or this
            *upscaleInputUI(),
            *qualityInputUI(),
        ]

@callback(
    Output('text', 'children'),
    Input('div_processParamUI', 'children'),
    State({'type':'input','id': ALL}, 'value'),
)
def show(_, values):
    return str(values)



if __name__ == '__main__':

    app.run(
        host=ip,
        port=port,
        debug=True,
    )
    

can we have [ {'id':'id1, 'value':3} ] in this format when State({'type':'input','id': ALL}, 'value') like this ?

Originally posted by @luewh in #2368

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the minimal Dash application in the issue and observe the values returned by the State({'type':'input','id': ALL}, 'value') callback. Trace the pattern-matching callback handling that determines the ordering, then add or update coverage so the result preserves each input's id/value association in the requested format.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.