-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Input output callback #1525
Input output callback #1525
Conversation
Thanks @chadaeschliman - this is really interesting. I think you're correct that logically this is self-consistent: any time one of the inputs to this callback changes, we should execute the callback exactly once and whatever values it returns become the final values of the input/output props. This pattern could also be used for input validation. @chriddyp @Marc-Andre-Rivet thoughts? Am I missing anything? Any reason we wouldn't want to allow this kind of circularity? There are a number of cases we'll need to write CI tests for. Consider this set of callbacks where cb1:
Output('a', 'value'), Output('b', 'value'), Output('c', 'value'),
Input('e', 'value'), Input('a', 'value'), Input('b', 'value')
cb2:
Output('d', 'value'),
Input('a', 'value') If you change If you change |
Thanks @alexcjohnson for considering this. You were correct that depending on the order the callbacks were defined, sometimes cb2 would be called twice (first with the original value then with the new value). The issue was that initially there were no "readyCallbacks" because cb1 depended on itself and so the fallback code was triggered which resulted in cb2 firing first. I made a straightforward fix by modifying |
🎉
Make the circular callback actually change the values, and make the downstream callback return different values depending on which of the values it receives. Then all you have to do is inspect the final contents of each element, and count how many times each callback has been executed using a
If both of those come out right, we know the order was correct. |
Thanks @alexcjohnson for the tip. I added test cbsc015 which checks this. I'm not sure why percy/dash failed on the latest build. |
The new test looks great! Don't worry about the Percy failure, that came from some authorization issues we're working through with CircleCI. It occurs to me it would be good to have the same test also with both callbacks clientside, since that can have different sequencing. That obviously can't use a And unless @Marc-Andre-Rivet has anything else to add, the only other thing I think we need is a changelog entry. |
Good idea. I added clsd014 which is the clientside version of cbsc015. I've never used clientside callbacks before. It seemed pretty straightforward but please check it over and make sure I implemented it correctly. Thanks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, your clientside test looks great - hah, these days we're recommending putting the js function inline like this:
dash/tests/integration/callbacks/test_wildcards.py
Lines 140 to 149 in 3402cb8
app.clientside_callback( | |
""" | |
function(vals) { | |
var len = vals.length; | |
return len < 2 ? len : +(vals[len - 1] || 0) + +(vals[len - 2] || 0); | |
} | |
""", | |
Output({"i": MATCH}, "children"), | |
Input({"i": ALLSMALLER}, "children"), | |
) |
But ironically we haven't included that form in test_clientside
🙄
Looks great in the callback graph - here's your app plus one downstream callback:
So I think we're good to go - thanks again for the PR! 💃
Yeah! Thanks for your help! |
I have an exact opposite use-case to the prunning implemented here - I need a callback to actually fire in an infinite circular fashion - see #2139 for details. Would be great if we could have an option to avoid this infinite loop (of a single callback) instead of prunning as it is done here. |
Allow circular callbacks in the special case of passing a component+property as an input and output of the same callback. By combining this capability with
dash.callback_context
it is straightforward to have multiple components remain synchronized. Other forms of circularity (involving multiple callbacks) are still detected and blocked. This is related to: #889Example code for a linked slider and numeric input:
Result:
Contributor Checklist