Hi everyone!
I just started playing with Dash and I have made a dashboard app where I render multiple html table based on dataframe (they have dynamic ids assigned in order to render them) and I have the following code which gets a dataframe
def multiindex_table(df, report_name, tab_name, index):
pos = np.diff(df.index.codes, axis=1, prepend=-1)
for row in pos:
counts = np.diff(np.flatnonzero(np.r_[row, 1]))
row[row.astype(bool)] = counts
cols = []
for name, version in df.columns:
if name in cols:
continue
cols.append(name)
first = [html.Th(n, style=header_style) for n in ["", titles[0]]] + [
html.Th(n, colSpan=2, style=header_style) for n in cols]
second = [html.Th(n, style=header_style) for n in [titles[1], "Version"]] + [
html.Th(n[1], style=header_style) for n in df.columns]
table_header = html.Thead([
html.Tr(first, style=row_style),
html.Tr(second, style=row_style)
], )
bodyTrs = []
for rowIndex, (rowSpanVals, idx, col) in enumerate(zip(pos.T, df.index.tolist(), df.to_numpy())):
rowTds = []
for name, rowSpan in zip(idx, rowSpanVals):
if rowSpan != 0:
rowTds.append(html.Td(name, rowSpan=rowSpan, style=row_style))
for i in range(0, len(col), 2):
cell_id = {
'type': 'table-cell',
'report_name': report_name,
'tab_name': tab_name,
'index': index,
'row_variant': idx[0],
'row_tag': idx[1],
'col_version': df.columns[i][0],
'col_level': 'main',
'col_index': i,
'row_index': rowIndex
}
rowTds.append(html.Td(id=cell_id, children=col[i], style=row_style, n_clicks=None))
rowTds.append(html.Td(id=cell_id, children=col[i + 1], style=row_style, n_clicks=None))
bodyTrs.append(html.Tr(rowTds, style=row_style))
return table_header, html.Tbody(bodyTrs)
As you can see I also assign for each cell an id in order to be able to display some data if a click happens on them, which I do with this callback
@app.callback(
Output({'type': 'some-table', 'report_name': MATCH, 'tab_name': MATCH, 'index': MATCH}, 'children'),
Input({'type': 'table-cell', 'report_name': MATCH, 'tab_name': MATCH, 'index': MATCH, 'row_variant': ALL,
'row_tag': ALL, 'col_version': ALL, 'col_level': ALL, 'col_index': ALL, 'row_index': ALL},
'n_clicks'),
prevent_initial_call=True
)
def cell_click(n_clicks):
ctx = callback_context
# ... code that returns some data
Now everything works like a charm, the only thing that bothers me is that when there is a click on a cell, it’s like every cell was clicked. For example the inputs of ctx are 192 elements (or n_clicks for this matter returns a list of 192 elements), which matches with the 192 cells.
I wanted to know if this could impact efficiency, and if so how can I only retrieve the only cell that was clicked. I know that its because of the wildcarde since Ive used the ALL keywords for the other fields in the input, but if I try to replace all those ALL witch MATCH, then there will be an error asw the Output wildcard wont match the Input one (and I dont want the Output one to have all the same fields as the Input as I want to display information on some table when a cell is clicked, I dont want each of one of the cell to have their own dedicated table that re renders each time because it seems unefficient but perhaps I might be wrong).
Therefore I just wanted to know if the actual solution I have is the best for my use case or if there is a better one.
I’ll be happy to provide more informations if needed!
Thank you very much for your help and time