Hey guys,
I have created an accordion component using pattern matching callback + calback_context
As the pattern matching component is so powerful, I’m sure that it can be useful to some people, so I would like to share with you all the solution I found, but would love to know if it exists a better way to do this
import dash_bootstrap_components as dbc
import dash_html_components as html
from dash.dependencies import Input, Output, State, ALL
import dash
# CSS files and links
external_stylesheets = [dbc.themes.BOOTSTRAP,
'https://use.fontawesome.com/releases/v5.8.1/css/all.css',
]
app=dash.Dash(__name__,
external_stylesheets=external_stylesheets,
meta_tags=[{"name": "viewport",
"content":"width=device-width, initial-scale=1, maximum-scale=1"
}],)
example_json={"Options1":["example1", "example2", "example3"],
"Option2":["example4", "example5", "example6"],
"Option3":["example7", "example8", "example9"]}
def accordeon_comp(i):
internal_options_list = example_json[i]
return html.Div(
[
html.Div(
html.Div([
dbc.Button([html.Span(html.I(className="fas fa-plus plus-color-accord",
id={
'type': 'font-awesome-plus-icon',
'index': i
}
)), f" {i}"],
color="black",
id={
'type': 'accord-btn',
'index': i
},
n_clicks=0,
),
dbc.Collapse(
[dbc.Card(html.Div([card_name],
id={
'type': 'industry-options',
'index': card_name
}
), style={"width":"250px"}
) for card_name in internal_options_list],
id={
'type': 'content-accordeon',
'index': i
},
is_open=False,
)]
)
),
])
accordion_component = html.Div(
[accordeon_comp(val) for val in [val for val in list(example_json.keys())]],
className="accordion"
)
app.layout = html.Div(accordion_component)
@app.callback(
Output({'type': 'content-accordeon', 'index': ALL}, 'is_open'),
Output({'type': 'font-awesome-plus-icon', 'index': ALL}, 'className'),
Input({'type': 'accord-btn', 'index': ALL}, 'n_clicks'),
State({'type': 'content-accordeon', 'index': ALL}, 'is_open')
)
def display_output(_, is_open):
ctx = dash.callback_context
if not ctx.triggered:
plus_open_icon="fas fa-plus"
plus_close_icon="fas fa-minus"
return is_open, [plus_open_icon if entry == False else plus_close_icon for entry in is_open]
else:
button_id = ctx.triggered[0]['prop_id'].split('.')[0]
triggered=eval(button_id)['index']
state_object=ctx.states
inputs=ctx.inputs
is_open_original=is_open.copy()
is_open = [True if eval(val.split(".")[0])['index'] == triggered else False for val in state_object]
index_change = [n for n, val in enumerate(state_object) if eval(val.split(".")[0])['index'] == triggered]
if is_open_original == is_open:
is_open[index_change[0]] = not is_open[index_change[0]]
else:
pass
plus_open_icon="fas fa-plus"
plus_close_icon="fas fa-minus"
return is_open, [plus_open_icon if entry == False else plus_close_icon for entry in is_open]
if __name__ == '__main__':
app.run_server(debug=True, port="4487")
It is an adaptation of the accordion shown on the dbc.collapse;
Hope that it can be useful to someone;
REgards,