-
-
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
475 Pattern Matching Callbacks (codenamed wildcards) #1103
Conversation
- new _validate.py to centralize error checking - dash exceptions auto-dedent - clean up usage and cruft
Dear @alexcjohnson |
@christianwengert Absolutely! Thank you for your patience with this. I will try to post some usage examples here later today. |
Yes, an usage example would be great for getting started
… On 31 Jan 2020, at 15:44, alexcjohnson ***@***.***> wrote:
@christianwengert Absolutely! Thank you for your patience with this. I will try to post some usage examples here later today.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
To-Do list exampleThe import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State, MATCH, ALL
app = dash.Dash(__name__)
app.layout = html.Div([
html.Div('Dash To-Do list'),
dcc.Input(id="new-item"),
html.Button("Add", id="add"),
html.Button("Clear Done", id="clear-done"),
html.Div(id="list-container"),
html.Hr(),
html.Div(id="totals")
])
style_todo = {"display": "inline", "margin": "10px"}
style_done = {"textDecoration": "line-through", "color": "#888"}
style_done.update(style_todo)
@app.callback(
[
Output("list-container", "children"),
Output("new-item", "value")
],
[
Input("add", "n_clicks"),
Input("new-item", "n_submit"),
Input("clear-done", "n_clicks")
],
[
State("new-item", "value"),
State({"item": ALL}, "children"),
State({"item": ALL, "action": "done"}, "value")
]
)
def edit_list(add, add2, clear, new_item, items, items_done):
triggered = [t["prop_id"] for t in dash.callback_context.triggered]
adding = len([1 for i in triggered if i in ("add.n_clicks", "new-item.n_submit")])
clearing = len([1 for i in triggered if i == "clear-done.n_clicks"])
new_spec = [
(text, done) for text, done in zip(items, items_done)
if not (clearing and done)
]
if adding:
new_spec.append((new_item, []))
new_list = [
html.Div([
dcc.Checklist(
id={"item": i, "action": "done"},
options=[{"label": "", "value": "done"}],
value=done,
style={"display": "inline"}
),
html.Div(text, id={"item": i}, style=style_done if done else style_todo)
], style={"clear": "both"})
for i, (text, done) in enumerate(new_spec)
]
return [new_list, "" if adding else new_item]
@app.callback(
Output({"item": MATCH}, "style"),
[Input({"item": MATCH, "action": "done"}, "value")]
)
def mark_done(done):
return style_done if done else style_todo
@app.callback(
Output("totals", "children"),
[Input({"item": ALL, "action": "done"}, "value")]
)
def show_totals(done):
count_all = len(done)
count_done = len([d for d in done if d])
result = "{} of {} items completed".format(count_done, count_all)
if count_all:
result += " - {}%".format(int(100 * count_done / count_all))
return result
if __name__ == "__main__":
app.run_server(debug=True) |
I noticed a problem with the To-Do app: if you delete all the items, the totals callback will not fire to say "0 of 0 items completed" as it should. This is because we currently only fire callbacks based on inputs that exist when they're fired, but for Working on a fix for this... |
At a meeting where I demoed this feature, the consensus was We didn't discuss Give me a 👍 reaction (not a comment please) if the names |
|
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.
💃💃💃 🚢 ⛵️ 🎉🎉🎉
The issue @chriddyp mentioned #1103 (comment) from the docs, that the title never goes back from "Updating...", is still present. Investigating... |
Ah got it - we're creating and throwing some errors that I forgot to trap, so I could clear the associated callback from the queue and surface the error in the devtools. The specific error we're hitting in the docs is (in case someone wants to fix it):
|
so we can clear the pendingCallbacks queue and show errors in the devtools
After 7c47b05 (running docs with devtools on so we see the errors... with devtools off the title is still correct and the errors only appear in the js console) |
whats that rationale behind the restriction that I cannot combine |
That’s essentially it - the value to return into that single output would be ill-defined, as it would be trying to get a separate value from each matched input. I see how specifically with In this case I would suggest either making a separate |
When I used two outputs, one of which uses MATCH and the other has nothing to do with 'index': it raised an error as follows: In the callback for output(s): Why is it necessary to require all the outputs with MATCH, and how can I solve this problem? |
@lhsusan1016 as described in #1103 (comment) if there were two different elements that satisfy your You can solve this by either switching to an I happened to see your comment, but old closed PRs are not great places to start conversations. This kind of question is better at https://community.plotly.com |
Pattern Matching Callbacks! (Codenamed, Wildcards!)
➡️ See official documentation here: https://dash.plotly.com/pattern-matching-callbacks
Closes #475 - using the API discussed there (I'll post some examples soon, but for now here's the description):
id={"type": "cat", "age": 4, "purrs": True}
MATCH
,ALL
, andALLSMALLER
- and can be imported fromdash.dependencies
. There are various rules about how these can combine, driven by the need to resolve these to a unique callback invocation for each set of outputs and identify uniquely the inputs required for this invocation...To do before this is ready:
Contributor Checklist
CHANGELOG.md
Closes #832 (among other callback bugs - the others all have commits that close them with matching tests, but #832 is a bit heavy for a test of its own)
Closes #1146