Based on this feature request, I have been playing around with a new callback syntax that resembles the function signature more closely. To illustrate the idea, consider this (very simple) app,
from dash import callback, html, dcc, Input, Output, State, Dash
@callback([Output("hello", "children"), Output("click", "children")],
Input("btn", "n_clicks"), State("name", "value"))
def hello(n_clicks: int, name):
return f"Hello {name}!", f"Click count is {n_clicks}"
app = Dash(prevent_initial_callbacks=True)
app.layout = html.Div([
dcc.Input(placeholder="Enter your name here", id="name"),
html.Button("Click me!", id="btn"),
html.Div(id="hello"), html.Div(id="click")
])
if __name__ == '__main__':
app.run_server()
that prints hello and click count messages on click. With the new syntax, the code would be,
from dash_extensions.enrich import DashProxy, callback, html, dcc, prop
@callback
def hello(n_clicks: prop("btn", "n_clicks", int),
name: prop("name", "value", trigger=False)) \
-> tuple[prop("hello", "children"), prop("click", "children")]:
return f"Hello {name}!", f"Click count is {n_clicks}"
app = DashProxy(prevent_initial_callbacks=True)
app.layout = html.Div([
dcc.Input(placeholder="Enter your name here", id="name"),
html.Button("Click me!", id="btn"),
html.Div(id="hello"), html.Div(id="click")
])
if __name__ == '__main__':
app.run_server()
A few notes on the new syntax,
- The
Input/Output/Stateobjects are replaced by a commonpropfunction that takes component id and component property as mandatory arguments, and optionally a type definition - Argument props are interpreted as
Input, orStateiftrigger=False - Return props are interpreted as
Output, orServersideOutputifserverside=True
On thing I like about the new syntax is that the binding to the prop happens just next to the argument name definition, e.g.
n_clicks: prop("btn", "n_clicks", int)
That means that you don’t have to look elsewhere in the code (with the current syntax, in a list above that could be arbitrarily long) to figure out what property (i.e. “n_clicks” of “btn”) the “n_clicks” argument binds to. I think that improves code readability.
Secondly, the new syntax is more compact (at least in the current form). Rather than importing “Input/Output/State”, you only need a single “prop” import. And the dependency type (i.e. “Input”, “Ouput”, etc.) is derived from the function signature. Especially for people that know Python, I think this might feel more “natural” as compared to learning a syntax just for Dash (i.e. the current “Input/Output/State” syntax).
You should be able to try out the new syntax with the following rc release,
Let me know what you think. Any suggestions for improvements are very welcome 
This is really, really cool. I like the syntax for the same reasons as you mention: terser & clearer relationship between prop and input variable.