Pattern matching question for id with multiple keys

Hi, I have made a simple study regarding some questions I still have about pattern matching.

import dash
from dash import Dash,html,ctx
from dash.dependencies import Input, Output,State,MATCH, ALL
import dash_bootstrap_components as dbc
import json 


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

app.layout = html.Div([
    dbc.Button('Case 1',id='button_1'),
    dbc.Button('Case 2',id='button_2'),
    dbc.Button('Case 3',id='button_3'),
    dbc.Button('Case 4',id='button_4'),
    
    dbc.Button('Clear result',id='clear_button'),
    
    #case 1&2 input
    
    html.P(id={"type":"input","index":1}),
    html.P(id={"type":"input","index":2}),
    html.P(id={"type":"input","index":1,"attribute":"a"}),
    html.P(id={"type":"input","index":2,"attribute":"a"}),
    html.P(id={"type":"output","index":1}),
    html.P(id={"type":"output","index":2}),
    html.P(id={"type":"output","index":1,"attribute":"a"}),
    html.P(id={"type":"output","index":2,"attribute":"a"}),
    
    #case 3&4 input
    html.P(id={"type":"input2","index":1}),
    html.P(id={"type":"input2","index":2}),
    html.P(id={"type":"input2","index":1,"attribute":"a"}),
    html.P(id={"type":"input2","index":2,"attribute":"a"}),
    html.P(id={"type":"input2","index":1,"attribute":"b"}),
    html.P(id={"type":"input2","index":2,"attribute":"b"}),
    
    html.Hr(),
    html.P('Case 1 result:'),
    html.P("Attempted to to print all state 'id' containing 'index' key, using only"+
           " 'index' key: FAILED, return nothing."),
    html.Div(id="print_output"),
    html.Hr(),
    html.P('Case 2 result:'),
    html.P("Attempted to to print all state 'id' containing 'index' key, using "+
           " 'index' and 'type' key: FAILED, missing 'id' with 'attribute' key."),
    html.Div(id="print_output_2"),
    
    html.Hr(),
    html.P('Case 3 result:'),
    html.P("Attempted to to print all state&output with matching 'id' contains 'index' key, using only"+
           " 'index' and 'type' key: FAILED, missing all 'id' with 'attribute' key."),
    html.P(id={"type":"output2","index":1}),
    html.P(id={"type":"output2","index":2}),
    
    html.Hr(),
    html.P('Case 4 result:'),
    html.P("Attempted to to print all state&output with matching 'id' contain 'index' key, using all"+
           " 'index','type' and 'attribute': SUCCESS, returned all 'id' contain 'attribute' key"),
    html.P(id={"type":"output2","index":1,"attribute":"a"}),
    html.P(id={"type":"output2","index":2,"attribute":"a"}),
])

@app.callback(
    Output('print_output','children'),
    Input('button_1','n_clicks'),
    Input('clear_button','n_clicks'),
    State({"index":ALL},'children'),
    prevent_initial_call=True
    )
def check_all_state_1(click,clear,element):
    n = len(element)
    if ctx.triggered_id=="clear_button":
        return [dash.no_update for _ in range(n)],[]
    else:
        ctx_msg = json.dumps({
            'states': ctx.states,
        }, indent=2)
        
        return html.Pre(ctx_msg)

@app.callback(
    Output('print_output_2','children'),
    Input('button_2','n_clicks'),
    Input('clear_button','n_clicks'),
    State({"type":"input","index":ALL},'children'),
    prevent_initial_call=True
    )
def check_all_state_2(click,clear,element):
    if ctx.triggered_id=="clear_button":
        return []
    else:
        ctx_msg = json.dumps({
            'states': ctx.states
        }, indent=2)
        
        return html.Pre(ctx_msg)

@app.callback(
    Output({"type":"output2","index":MATCH},'children'),
    Input('button_3','n_clicks'),
    Input('clear_button','n_clicks'),
    State({"type":"input2","index":MATCH},'children'),
    prevent_initial_call=True
    )
def check_match_state_1(click,clear,element):
    if ctx.triggered_id=="clear_button":
        return []
    else:
        ctx_msg = json.dumps({
            'states': ctx.states,
            'outputs':ctx.outputs_list
        }, indent=2)
        return html.Pre("Match result:\n" + ctx_msg)
    
@app.callback(
    Output({"type":"output2","index":MATCH,'attribute':'a'},'children'),
    Input('button_4','n_clicks'),
    Input('clear_button','n_clicks'),
    State({"type":"input2","index":MATCH,"attribute":ALL},'children'),
    prevent_initial_call=True
    )
def check_match_state_2(click,clear,element):
    if ctx.triggered_id=="clear_button":
        return []
    else:
        ctx_msg = json.dumps({
            'states': ctx.states,
            'outputs':ctx.outputs_list
        }, indent=2)
        return html.Pre("Match result:\n" + ctx_msg)

if __name__ == '__main__':
    app.run(debug=True)

From the results, I have a couple of questions.

First, does pattern matching always use input keys to find an exact match (exclude id with more/less keys if not specify in the match pattern) or is there another way to bypass this?

Second, Is there any way to make pattern matching return match id without the need to list all keys in the match pattern? This is hard to implement if id contains lots of keys.

Thanks.

1 Like