Dash extensions - dcc.Dropdown value callback triggered by options change

Hi, I have a simple scenario using TriggerTransform from dash extensions.
image
And I want the text field to show a value (current timestamp) only when the value in the 2nd dropdown menu or the checklist is changed. However, the text field is changed also when only changing the options of the 2nd dropdown menu (that are assigned by the 1st dropdown menu value).
Is this a feature, a known bug, or am I missing something?

See the code below :

from dash_extensions.enrich import Output, Input, Trigger
from dash import dcc, html
import dash_bootstrap_components as dbc
from dash_extensions.enrich import DashProxy, TriggerTransform
import time

app = DashProxy(__name__, transforms=[TriggerTransform()])
app.layout = html.Div([
    html.Div([
        "Dropdown1",
        dcc.Dropdown(id="my-dropdown1", options=[{'label': 'a', 'value': 'a'}, {'label': 'b', 'value': 'b'}])
    ]),

    html.Div([
        "Dropdown2",
        dcc.Dropdown(id="my-dropdown2")
    ]),
    html.Div([
            dbc.Checklist(
                options=[{"label": "label 1", "value": 0}, {"label": "label 2", "value": 1}],
                value=[0],
                id="my-checklist",
                inline=True
            )
        ]),
    html.Div([
        "Text field",
        html.Div(id="my-text-field")
    ])

])


@app.callback(
    Output('my-dropdown2', 'options'),
    Input('my-dropdown1', 'value')
)
def on_1_selected(source):
    if source == 'a':
        vehicle_list = [1, 2, 3, 4]
    else:
        vehicle_list = [10, 20, 30, 40]
    return [{'label': n, 'value': n} for n in vehicle_list]


@app.callback(
    Output('my-text-field', 'children'),
    Input('my-dropdown2', 'value'), Trigger('my-checklist', 'value')
)
def on_2_selected(value):
    if value is None:
        value = time.time()
    return value


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

Try changing from Input to State for the component my-dropdown

Hi AIMPED, if I use State instead of Input in the 2nd callback it never gets called when I choose a value from the component my-dropdown2.
Or did you mean something else?

Yes, you are right. This seems strange, why do you use the TriggerTranfsorm? Couldn’t you use just the checklist value as trigger?

why do you use the TriggerTranfsorm? Couldn’t you use just the checklist value as trigger?

I could, and I did, but both Input and Trigger lead to the same behavior.

Wow, the behavior of your example is strange, and I can’t see the reason for this. Must be something obvious?

I created a MRE which does the same as your example but works as expected:

import dash
from dash import dcc, html, Input, Output, ctx

app = dash.Dash(__name__)
app.layout = html.Div([
    dcc.Dropdown(id='d1', options=[1, 2, 3]),
    dcc.Dropdown(id='d2', options=[]),
    dcc.Checklist(id='check', options=['d', 'e']),
    html.Pre(id='out')
])


@app.callback(
    Output('d2', 'options'),
    Input('d1', 'value'),
    prevent_initial_call=True
)
def update(val):
    return {
        1: ['a', 'b'],
        2: ['A', 'B'],
        3: ['x', 'y'],
    }[val]


@app.callback(
    Output('out', 'children'),
    Input('d2', 'value'),
    Input('check', 'value'),
    prevent_initial_call=True
)
def update(drop, chk):
    trigger = ctx.triggered_id
    return {
        'd2': drop,
        'check': chk
    }[trigger]

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

The Trigger component just removes the property value from the callback signature, i.e. the expected/intended behavior in terms of triggering the callback is to do the same as Input.

I just tried running your example, and it seems to do exactly what you want? If I change drop down 1, the value of drop down 2 is cleared, and the text remains unchanged. Please elaborate if this is not the intention?

Animation4

Hi @Emil Right at the start of your gif when selecting option a the text changes. I think this is not wanted.

But I have to confess, I’m not sure :see_no_evil:

You’re right @AIMPED. @Emil, your gif shows the unintended behavior at the start. I don’t wan’t Dropdown1 to change the text field. However here whenever Dropdown2 has no value, that text field is changed when you choose a value for Dropdown1.

It doesn’t, unfortunately. When you choose a value from Dropdown1, the callback triggered by a value in Dropdown2 gets called, although with a value=None.