How can I add an input that is selected by a click

haha - this is a lot of fun! I was trying to think of an example for pattern matching callback for the Dash Example Index and this topic inspired me.

By using pattern matching callbacks, you can avoid having 52 inputs in the callback.

I’ll probably turn this into some type of simple game for the Example Index, but in the meantime, here’s my version:

card_game

import random
from dash import Dash, html, Input, Output, ALL, ctx
import dash_bootstrap_components as dbc
from dash_iconify import DashIconify

app = Dash(__name__, external_stylesheets=[dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP])

SUITS = ["spades", "clubs", "diamonds", "hearts"]
RANKS = ["ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "jack", "queen", "king"]


def create_deck(shuffle=False):
    """Create a  deck of 52 cards"""
    deck = [(s, r) for s in SUITS for r in RANKS]
    if shuffle:
        random.shuffle(deck)
    return deck


def make_card(card):
    """format the card as a button"""
    suit, rank = card
    color = "black" if suit in ["spades", "clubs"] else "red"
    card_icon = DashIconify(
        icon=f"game-icons:card-{rank}-{suit}", color=color, height=60
    )
    return dbc.Button(
        [card_icon], color="white", className="p-0", id={"index": f"{suit}-{rank}"}
    )


def deck_layout(deck):
    """make card layout"""
    return [dbc.Row(dbc.Col([make_card(c) for c in deck if s in c])) for s in SUITS]


deck = create_deck()

app.layout = dbc.Container(
    [
        html.H1("Select a Card"),
        html.Div(deck_layout(deck)),
        html.H2("You Selected:"),
        html.Div(id="card-selected"),
    ]
)


@app.callback(
    Output("card-selected", "children"),
    Input({"index": ALL}, "n_clicks"),
    prevent_initial_call=True,
)
def selected(_):
    selected_card = ctx.triggered_id.index
    suit, _, rank = selected_card.partition("-")
    color = "black" if suit in ["spades", "clubs"] else "red"
    return DashIconify(icon=f"game-icons:card-{rank}-{suit}", color=color, height=60)

if __name__ == "__main__":
    app.run_server(debug=True)


4 Likes