Hello!
I have a dash app. Its essence is to make a request to the database every 30 seconds and update the page according to them. The data is divided into 11 blocks, some of which may be empty. If they are empty, then I don’t show it completely.
Each block has a row with a title (1) and a table with rows (2) (screenshot).
I need to add a button to the title bar that will hide the table (2). I did this via a button callback with indexes.
@callback(
Output({"type": "dynamic-card", "index": MATCH}, "style"),
Input({"type": "dynamic-button", "index": MATCH}, "n_clicks")
)
But due to the fact that every time new data can appear and new blocks can be created, I recreate the buttons. Therefore, their n_clicks = 0
and hidden blocks are revealed again.
I tried writing the n_clicks
of each button to a file and reading them before updating. But it turns out that hiding will be the same for all users, but I need it separately for each.
My question is how to save n_clicks
after updating? (and for each user to remain hidden for the duration of their session).
My code (removed the import of all styles for convenience, the page looks like the screenshot):
from dash import dcc, html, Input, Output, callback, MATCH, ctx
from datetime import datetime
import dash_bootstrap_components as dbc
refreshing_data = [
[],
[],
[],
[[1, '16/09 12:00', 'name', 'https://google.com/', 'status', '1 day 1 h', '1 day 1 h']],
[[1, '16/09 12:00', 'name', 'https://google.com/', 'status', '1 day 1 h', '1 day 1 h']],
[],
[],
[],
[],
[],
[[1, '16/09 12:00', 'name', 'https://google.com/', 'status', '1 day 1 h', '1 day 1 h']],
'Last refresh at 15:19'
]
switch_case = {
0: 'H0',
1: 'H1',
2: 'H2',
3: 'H3',
4: 'H4',
5: 'H5',
6: 'H6',
7: 'H7',
8: 'H8',
9: 'H9',
10: 'H10'
}
def template_small_card(row):
date_req = row[1]
operation = row[2]
link = row[3]
status = row[4]
card = html.Div([
html.H6("Content is {}, {}, {}, {}".format(date_req, operation, link, status))
],
)
return card
def template_big_card(list_of_small_cards, big_name):
n = big_name
card = html.Div(
[
html.Div([
# button to hide the block
html.Div(
[
html.Button(children=[html.Img(src='assets/vector1.png')],
n_clicks=0,
id={"type": "dynamic-button", "index": n},
),
],
),
html.Div([
html.H4("{}".format(big_name), className="card-title", ),
], ),
],
),
html.Hr(),
# I plan to hide this block
html.Div([
*list_of_small_cards
],
id={"type": "dynamic-card", "index": n}
)
],
)
return dbc.Row(children=[card], className="g-0")
def generate_big_card(data, big_name):
if not data:
return []
else:
result = []
for ind in data:
small_card = template_small_card(ind)
result.append(small_card)
big_card = template_big_card(result, switch_case[big_name])
return big_card
layout = html.Div([
html.Div('Request queue'),
html.H6(id='time_update_1_vert'),
dcc.Interval(
id='interval-component_vert',
interval=30 / 60 * 60000,
n_intervals=0
),
dbc.Row(id='row-tables_vert')
],
)
@callback(
Output('time_update_1_vert', 'children'),
Output('row-tables_vert', 'children'),
Input('interval-component_vert', 'n_intervals'),
)
def update_data(n_intervals):
list_of_df = refreshing_data
columns_for_row = []
time_update = datetime.today().strftime('%Y-%m-%d %H:%M:%S')
for i in range(0, 11):
dbc_column = generate_big_card(list_of_df[i], i)
if dbc_column:
columns_for_row.append(dbc_column)
return time_update, columns_for_row
@callback(
Output({"type": "dynamic-card", "index": MATCH}, "style"),
Input({"type": "dynamic-button", "index": MATCH}, "n_clicks")
)
def update_card(n_clicks):
if n_clicks % 2 == 1:
style1 = {'display': 'none'}
else:
style1 = {}
return style1