Hi, I’m struggling with the pattern matching callbacks. I’m trying to save input from a textArea and a ‘save’ modal’s input field to local storage, have a callback that generates a ‘load’ modal table with rows as [title, text, loadBtn, deleteBtn] from the saved data, and allows for the dynamically generated deleteBtns to also modify the stored data. Another callback will take the load modal’s LoadBtn as input, Output(‘text_input’, ‘value’) with the state of the row’s corresponding text value.
I’ve put together a simple application to show where I’m at. I have the actual application working except for the deleteBtn and loadBtn part which is when I realized I probably need to use pattern matching callbacks for the dynamically generated buttons since there is no way to get the IDs of those without a callback. I’ve done similar in plain javascript and html using global vars.
Currently, the callback inserts the entered title:text to storage (as well as an initial ‘null’:None) but doesn’t insert any new entries after the first ‘save’ click. I thought setting the text_storage output and state to index:0 would work but it doesn’t :/. Any advice is greatly appreciated.
I’ve read How to save and access multiple data frames from dcc.Store in plotly dash - #3 by UdayGuntupalli but am still a tad lost.
import dash
from dash import dcc, html, dash_table
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State, ALL, MATCH
#server
app = dash.Dash(__name__, suppress_callback_exceptions=False, external_stylesheets = [dbc.themes.BOOTSTRAP, dbc.icons.FONT_AWESOME])
server = app.server
body = dbc.Container(
[
dbc.Row(
dbc.Textarea(id="text_input", className='mb-3 border-primary', size="md", value='Testing storing text with dynamic modals'),
align="center",
),
dbc.Row(
html.Button(html.I(className="far fa-save"),
className=("btn bg-transparent "),
id='btn_save',
n_clicks=0,
),
),
dbc.Row(
html.Button(html.I(className="far far fa-folder-open"),
className=("btn bg-transparent "),
id='btn_load',
n_clicks=0,
),
)
]
)
save_modal = html.Div(
[
dbc.Modal(
[
dbc.ModalHeader(dbc.ModalTitle("Save Text")),
dbc.ModalBody([
dbc.Input(id="text_title"),
]),
dbc.ModalFooter(
dbc.Button(
[
html.I(className="far fa-folder-open")," Save",
dcc.Store(id={"type":"text_storage", "index": 'n_clicks'}, storage_type='local')
],
className="ms-auto btn-success mbp-3",
n_clicks= 0,
id={"type": "dynamic_save_btn","index": 'n_clicks'}
)
),
],
id='save_modal',
is_open=False
),
]
)
load_modal = html.Div(
[
dbc.Modal(
[
dbc.ModalHeader(dbc.ModalTitle("Load Text")),
dbc.ModalBody(id="load_modal_table"),
],
id='load_modal',
is_open=False
),
]
)
app.layout = html.Div([body, save_modal, load_modal])
#open/close save modal
@app.callback(
Output("save_modal", "is_open"),
Input("btn_save", "n_clicks"),
State("save_modal", "is_open"),
)
def toggle_modal(n1, is_open):
if n1:
return not is_open
return is_open
#open/close load modal
@app.callback(
Output("load_modal", "is_open"),
Input("btn_load", "n_clicks"),
State("load_modal", "is_open"),
)
def toggle_modal(n1, is_open):
if n1:
return not is_open
return is_open
#save text to browser storage
@app.callback(
Output({"type": "text_storage", "index": ALL}, "data"),
[Input({"type": "dynamic_save_btn","index": ALL}, "n_clicks")], #Input({"type": "delete", 'index': MATCH}, 'value')],
[
State("text_title", "value"),
State("text_input", "value"),
State({"type": "text_storage", "index": ALL}, "data")
]
)
def save_pattern_data(clicks, title, text, stored_text):
print(clicks)
print(f'Retrieved data: \n {stored_text}')
if stored_text is None:
stored_text={}
data = stored_text
data[title]=text
print(f'Saved data: {data}')
return data
if __name__ == '__main__':
app.run_server(debug=True)