plotly / plotly/dash

Adding Pattern Matching selector ALLELSE

Open
#3,206 2 comments 0 reactions 1 assignee View on GitHub

Nobody has claimed this yet.

cs feature P1
Dominant language
Python
Stars
24.4k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
13

Description

Similar to ALLSMALLER but doesn't asume that id index are numeric and sequential

Use case

General description

  • There's a set of components with the same pattern-matching id type.
  • Based on an interaction with one of those components (or with another component with the same pattern-matching id index), something about it will change.
  • That same property will also change in the rest of the components of the set, but with a different value.

Example

  • We have 6 clickable cards.
  • Each clickable card is an html.Div with pattern-matching id {'type':'card,'index': f"card_{i}"} wrapped in an html.A with pattern-matching id {'type':'invisible_button,'index': f"card_{i}"}.
  • When a user clicks one card, its style changes to HIGHLIGHT_STYLE (red) and the style of the rest changes to DEFAULT_STYLE (black).

https://github.com/user-attachments/assets/63e0d473-537c-4df7-bd04-140ad784b449

Desired behavior/code

@callback(
    Output({'type':'card','id': MATCH}, 'style'),
    Output({'type':'card','id': ALLELSE}, 'style'),
    Input({'type':'invisible_button','id': MATCH}, 'n_clicks'),
    )
def restore_card_format(n_clicks):
    return HIGHLIGHT_STYLE, [DEFAULT_STYLE]*5

Current behavior/code

@callback(
    Output({'type':'card','id': ALL}, 'style'),
    Input({'type':'invisible_button','id': ALL}, 'n_clicks'),
    )
def restore_card_format(n_clicks):
    return DEFAULT_STYLE

@callback(
    Output({'type':'card','id': MATCH}, 'style'),
    Input({'type':'invisible_button','id': MATCH}, 'n_clicks'),
    )
def highlight_card(n_clicks):
    return HIGHLIGHT_STYLE

Using the above code produces an error like this:

In the callback for output(s): {"id":MATCH,"type":"card"}.style Output 0 ({"id":MATCH,"type":"card"}.style) overlaps another output ({"id":ALL,"type":"card"}.style) used in a different callback.

Workaround - current way to implement this functionality:

from dash import Dash, Input, Output, callback, html, dcc, ALL, MATCH, ctx

app = Dash()
server = app.server

DEFAULT_STYLE = {
    "height":"200px",
    "width":"200px",
    "margin":"5px",
    "background-color": "black",
    "color":"white"
    }

HIGHLIGHT_STYLE = {
    "height":"200px",
    "width":"200px",
    "margin":"5px",
    "background-color": "red",
    }

app.layout = html.Div([
    html.A(
        html.Div(
            id={'type':'card','index': f"card_{i}"}, 
            style=DEFAULT_STYLE,
            children=f"card_{i}"
            ),
        id={'type':'invisible_button','index': f"card_{i}"}, 
        )
    for i in range(6)
], style={"display":"inline-flex"})

@callback(
    Output({'type':'card','index': ALL}, 'style'),
    Input({'type':'invisible_button','index': ALL}, 'n_clicks'),
    prevent_initial_call=True
    )
def highlight_card(n_clicks):
    selected_card_id = ctx.triggered_id["index"]
    # this is how ctx.outputs_list looks like
    # [{'id': {'index': 'card_0', 'type': 'card'}, 'property': 'style'}, {'id': {'index': 'card_1', 'type': 'card'}, ...]
    new_styles = [HIGHLIGHT_STYLE if card["id"]["index"]==selected_card_id else DEFAULT_STYLE for card in ctx.outputs_list]
    return new_styles

app.run(debug=True)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.