PMC - Variable property names discussion

Hi there,

I have a question. The thing is, when I need to use pattern matching to match some components that are associated, they have some different properties, I have to write an additional trigger to handle it.

like:

[
    State({"type": "parameter", "index": ALL}, "data"),
    State({"type": "parameter", "index": ALL}, "value"),
    State({"type": "parameter", "index": ALL}, "on"),
]

This makes my callback function very verbose and needs to regroup the parameters. While actually they are from several types of components, these trigger properties do not overlap. I vaguely remember that there was a post dedicated to this issue before, and someone has submitted a pr to change the name of the checklist’s values property to value, but I didn’t find it. However now that our component ecosystem is thriving, it is impossible and has no reason to require uniform property names.

I think passing a dictionary in is probably not easy to implement, so what if I specify the default trigger property in the id or simply define a property for each component to represent the default trigger property?

like:

[
    dcc.Input(id={"type": "parameter", "index": 1, "default": "value"}),
    daq.BooleanSwitch(id={"type": "parameter", "index": 2}, default="on"),
    dmc.Checkbox(id={"type": "parameter", "index": 3}, default="checked"),
]

Then the triggers can be simplified to:

[
    State({"type": "parameter", "index": ALL}, DEFAULT),
]

A callback might look like this.

@app.callback(
    Output(graph_1, "figure"),
    Input({"type": "parameter", "index": ALL}, DEFAULT),
    State({"type": "parameter", "index": ALL}, "id"),
)
def update(values, ids):
    params = {j["index"]: values[i] for i, j in enumerate(ids)}
    fig = do_something(**params)
    return fig

Or we can compose it before passing in.

@app.callback(
    Output(graph_1, "figure"),
    group=(
        [
            Input({"type": "parameter", "index": ALL}, DEFAULT),
            State({"type": "parameter", "index": ALL}, "id")["index"],
        ]
    ),
)
def update(params):
    fig = do_something(**params)
    return fig

Is this possible?

It’s not possible, but the idea is certainly worth exploring. As you mentioned, we’ve also been exploring ideas like making value the uniform parameter for most controls (migrating away from values).

We could also consider APIs like:

Input({'type': 'parameter', 'index': ALL}, ['value', 'values', 'rows'])

We’ve also thought about DEFAULT in the sense of being able to omit the property from Input or Output, so just @callback(Output('div'), Input('dropdown')). On the fence about this… explicit is better for learning, implicit is better once you know the “trick”.

Hi Chris,
Thanks for the reply! You mentioned better for learning, which reminds me of another potential optimization point.

The callback_context.triggered[0]["prop_id"].split(".")[0] is not very memorable. What if it is passed in as a parameter? like:

@app.callback(
    Output(my_output, "children"), Input(my_input, "value"), triggered_id=True
)
def update(triggered_id, value):
    if triggered_id != my_btn.id:
        return no_update
1 Like

Funny you mention that, @AnnMarieW actually just made a PR to Dash to improve this corner of the API… merged 5 days ago! Improved `callback_context` by AnnMarieW · Pull Request #1952 · plotly/dash · GitHub

@callback(
    Output("graph", "figure"), Input("btn-1", "n_clicks), Input("btn-2", "n_clicks)
)
def display(btn1, btn2):
   if  "btn-1.n_clicks" in ctx.triggered_ids:
       return update_graph1()
   if  "btn-2.n_clicks" in ctx.triggered_ids:
      return update_graph2()
2 Likes

Obviously, I’m lazy and don’t even want to import the context myself. :smirk: