-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Enhancing the callback function signature #159
Comments
Could something like enabling keyword arguments in @app.callback(Output('target', 'children'),
dropdowns = [Input(dropdown_id, 'value') for dropdown_id in DROPDOWN_IDS],
buttons = [Input(button_id, 'value') for button_id in BUTTON_IDS])
def func(dropdowns = [], buttons = []):
#etc... |
How would this work? As I understand it, Dash distinguishes between 2 cases for inputs: those that trigger the callback ( |
I am also interested in figuring out which event triggered the callback. My use case is navigation buttons, and right now the only way to figure it out is to store the vector of A possible improvement would be to include the event type that triggered the callback in the callback and the event emitter function signature. The latter would require also a change in dash-renderer. |
|
Update README.md
When creating more complex Dash apps, I've found that the function signatures of callbacks is somewhat limiting. More specifically:
Inputs and States are all combined together into the one list of positional parameters (ie
*args
) and you have to keep track of how many there of each in order to identify them from the args list. For a handful of Inputs/States, this is manageable, however if you're programmatically generating a large number of them (eg I recently made an app with 1600 Inputs -- granted this was more of a form than a reactive-viz) then this becomes trickier.In addition to keeping tabs on how many Inputs/States are being provided, in a larger app, you need to start managing the logic of how they are handled, as this can't be done explicitly for each input. My solution to this was to create a helper Store class which allowed me to to associate---for each input component that can be targeted by an Input/State---some of the handling logic while I'm constructing the layout, then retrieving the handling logic from this Store within the callback. The friction involved in this is again the simple positional arguments of callback functions, and having to associate them with the element IDs that have been added to the Store. I worked around this by having a method in the store to generate a list of Inputs for the callback signature and one to generate list of corresponding metadata dicts, then iterating over a those two lists zipped together:
If the callback signatures contained more information about each Input/State/Event, and in a manner more accessible, then these difficulties could be much lessened. For example, something along the lines of
callback(states, inputs, events)
where each positional argument is a dictionary---keyed perhaps by element_id.property---with values containing dicts which hold the component registration information for the relevant components involved in the callback eg: element_id, property, value.The important thing is that you be able to iterate over the callback's Inputs, States, and Events, and be able to readily access the associated element ID so that you can look it up in your own data structure. So those positional args could still just be lists of component registrations with the needed metadata, but the advantage of using dicts is that you could quickly index the registration you need without having to worry about where it was defined in the @app.callback decorator. (I guess that might would prompt the question of why the decorator needs to be lists then also)
I do however like the simplicity of the current callback signature, and for many simple apps it could be preferable. One option might be to create a more expressive callback function alongside the simple one that people can choose to use only when the situation calls for. Another compromise I see is to keep using only positional parameters, but have a flag in the callback decorator which toggles whether the arguments are a list of values or a list of {element_id, property, value} dicts.
See also this discussion in the community forums, where someone was running into the limitation of not being able to ascertain which element was the source of a
click
Event.The text was updated successfully, but these errors were encountered: