Skip to content

[Feature Request] Partial Pattern Matching #3764

@i-murray

Description

@i-murray

Summary

I use Dash pattern-matching callbacks extensively in my multi-page apps and make heavy use of the ALL wildcard. However, the callback architecture of my apps could be simplified further by introducing an option to allow partial matches, where a pattern with fewer keys matches components that have a superset of those keys.

This proposes an opt-in partial=True flag on Input, Output, and State.

Motivation

Currently, pattern-matching callbacks require the pattern and component to share exactly the same set of keys:

# Pattern: {"type": "btn", "index": ALL}
# Only matches: {"type": "btn", "index": 1}, {"type": "btn", "index": 2}
# Does NOT match: {"type": "btn", "index": 1, "page": "home"}

This forces developers to either:

  1. Ensure all related components have identical key sets (rigid, often impractical)
  2. Create separate callbacks for each key combination (verbose, duplicated logic)
  3. Use callback_context workarounds to multiplex unrelated callbacks

I find with my apps I frequently have components that share a conceptual "type" but differ in their additional metadata keys — pages, sections, tabs, permissions, etc.

Proposed API

from dash import Input, Output, State, ALL, MATCH

# Literal partial: matches all components with type="btn", regardless of extra keys
@app.callback(
    Output("output", "children"),
    Input({"type": "btn"}, "n_clicks", partial=True),
)
def handle_all_btns(n_clicks_list):
    # Receives a list (implicitly multi-valued since multiple components match)
    return f"Total: {sum(c or 0 for c in n_clicks_list)}"

# With ALL wildcard: collects all components that have a "type" key
@app.callback(
    Output("output", "children"),
    Input({"type": ALL}, "n_clicks", partial=True),
)
def handle_any_type(n_clicks_list):
    return f"Collected {len(n_clicks_list)} components"

# With MATCH: one-at-a-time on the shared key, ignoring extra keys
@app.callback(
    Output({"type": "display", "index": MATCH}, "children", partial=True),
    Input({"type": "btn", "index": MATCH}, "n_clicks", partial=True),
)
def handle_one(n_clicks):
    return f"Clicked {n_clicks} times"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions