Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Remove Callback Wildcard Restrictions (MATCH) #2462

Open
milind opened this issue Mar 16, 2023 · 11 comments
Open

[Feature Request] Remove Callback Wildcard Restrictions (MATCH) #2462

milind opened this issue Mar 16, 2023 · 11 comments
Assignees

Comments

@milind
Copy link

milind commented Mar 16, 2023

Is your feature request related to a problem? Please describe.
In trying to make my applications as modular as possible, I tend to use pattern-matching callbacks just about everywhere. There are many instances, however, where I need to be able to detect which component was triggered (via MATCH) and update a universal component.

Describe the solution you'd like
I would love for the restriction on the MATCH wildcard that requires the same number of MATCH values in the Input ID's and Output ID's to be lifted, allowing for more wildcards in the input than the output. It's my understanding that today's release of allow_duplicate in Dash's Output component should open the door to adding in the aforementioned solution.

Describe alternatives you've considered
The current solution for this use case is to use the ALL wildcard along with the callback context to filter down to the content that I'm ultimately interested in, but that solution does not scale especially well as it requires a lot of information to pass through the network, slowing things down.

@alexcjohnson
Copy link
Contributor

Thanks @milind

@T4rk1n I think "any MATCH present in the inputs must be present in all the outputs too" is another flavor of the restriction "every output can be connected to only one callback" - it's just that these duplicates come from the same function. So in the same way as we do for multiple callback functions we should be able to relax that restriction when the output that's missing a MATCH specifies allow_duplicate. Seem reasonable?

To make this concrete, I guess we're talking about callbacks that would look like:

@callback(
    Output("out", "children"),
    Input({"id": MATCH}, "n_clicks"),
    State({"id": MATCH}, "id"),
    prevent_initial_call=True
)
def cb(_, _id):
    return f"you clicked the button with id {_id['id']}"

@T4rk1n
Copy link
Contributor

T4rk1n commented Mar 17, 2023

I think the validation should be lifted entirely for Output, it makes MATCH awkward to use and I remember removing the validation without any breakage.

@alexcjohnson
Copy link
Contributor

It would have exactly the same kind of breakage scenarios as other duplicate outputs, an ambiguity when two callbacks result from the same stimulus. Which is why I think allowing it the same way (with allow_duplicate) makes most sense.

@olejorgenb
Copy link

olejorgenb commented Sep 14, 2023

I would also like this restriction to be lifted. I'm trying out a convention where callbacks which modify database state triggers a re-render using a "trigger" output. This does not work with this restriction in place.

For searchability - this is the error message:

`Input` / `State` wildcards not in `Output`s

or

Output X
does not have MATCH wildcards on the same keys as
Output Y
MATCH wildcards must be on the same keys for all Outputs. ALL  wildcards need not match, only MATCH

Someone else mentioned that they would like to do partial update based on a MATCH callback. On the surface this also sounds like a reasonable use-case (with the disclaimer that I haven't used partial update enough to really know it makes sense).

EDIT: Thinking a bit further - any scenerio where doing something to a component[1] should trigger a not-local-to-that-component update become cumbersome to implement. Only workaround (other than the one mentioned by OP) I can see is to add dummy outputs per component and route these to the callback implementing the global update.

[1] Which there can be an arbitrary number of

@RenaudLN
Copy link
Contributor

RenaudLN commented Nov 2, 2023

A current workaround to avoid the network cost of passing ALL to the callback would be:

  • to use ALL in a clientside callback, storing the information about the triggered input(s) at a level with as many MATCH as the desired Output
  • use the above store in a serverside callback to update the desired Output

Something like:

clientside_callback(
    """() => {
        return dash_clientside.callback_context.triggered.map(t => JSON.parse(t.prop_id.split(".")[0]))
    }"""
    Output("input_store", "data"),
    Input({"type": "btn", "id": ALL}, "n_clicks"),
)

@callback(
    Output("output", "children"),
    Input("input_store", "data"),
)
def myfunc(triggered_inputs_data):
    # ...

@pitris90
Copy link

pitris90 commented Feb 7, 2024

I would appreciate this restriction lifted too, as it would simplify my callbacks. I was so surprised it doesnt work when I tried to write similiar callback as you did.

@wilecoyote2015
Copy link

wilecoyote2015 commented Feb 20, 2024

I second the request, as this limitation if often problematic for our use cases.

@alvarodemig
Copy link

I agree. The current behavior is counterintuitive, as you can have the same output in multiple callbacks, and this would simplify many patterns.

@mmarfat
Copy link

mmarfat commented Apr 3, 2024

Any updates on this?

1 similar comment
@lunathanael
Copy link

Any updates on this?

@ndrezn
Copy link
Member

ndrezn commented Apr 21, 2024

Plotly team is looking into this as part of a future Dash release!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests