Currently I’m tying to implement workaround #3 from here: DataTable with filtering as well as components within cells
So basically I have a datatable and want to display additional information for a specific row when clicking on it. I have a first somewhat working version basically looking like that
infobox_clicks = 0
...
html.Div(id='infobox', style={'display': 'none'})
...
@app.callback(
Output('infobox', 'style'),
[Input('infobox', 'children'),
Input('infobox', 'n_clicks')])
def update_infobox_style(children, n_clicks):
global infobox_clicks
style = {'height': '300px', 'background-color': '#fff', 'position': 'fixed', 'margin': 'auto', 'top': '0', 'bottom': '0', 'left': '0', 'right': '0', 'border': '1px solid'}
if children and n_clicks == infobox_clicks or not n_clicks:
style['display'] = 'initial'
style['opacity'] = .85
return style
elif n_clicks > infobox_clicks:
style['display'] = 'none'
infobox_clicks += 1
return style
@app.callback(
Output('infobox', 'children'),
[Input('scenarios', 'active_cell'),
Input('scenarios', 'data')])
def get_selected_scenario(active_cell, data):
if active_cell:
return scenario_info_html(data[active_cell[0]], comm)
with scenario_info_html either returning some HTML elements or False. So the information to display gets stored int he infobox, but that one is just displayed when clicked on it and hidden again when clicked again.
But the problem is this stupid click counter. I theory everything would be fine by just using a n_clicks event on update_infobox_style, however that doesn’t work out since Dash doesn’t tell me which one of the inputs triggered the callback.
And of course this counter breaks once there are several people using it or the first one is just reloading the page. However packing the counter in an additional hidden div instead of a global variable is no solution either since update_infobox_style needs to write to it. But unfortunately callbacks are not allowed to have more than one output.
And even the messy option of coding the counter information into the infobox style doesn’t work out since a callback can’t have an output also as input, e.g. the following fails:
@app.callback(
Output('infobox', 'style'),
[Input('infobox', 'children'),
Input('infobox', 'n_clicks'),
Input('infobox', 'style')])
def update_infobox_style(children, n_clicks, style):
...
Is there some clean solution to that?