全部,
我正在尝试实现一个破折号数据表,我通过直接单击它来选择行(没有单选按钮)。目前,我正在使用 执行此操作,active_cell并且效果很好:无论用户单击行的哪个单元格,都会使用该行中的数据更新图表。如果他单击同一行中的另一个单元格,则未选择数据(通过 dcc.storage)
我的问题来了:如果用户再次单击同一个单元格,则不会active_cell触发任何事件。因此,我的回调没有被触发,也没有任何反应。我想在用户第二次单击该单元格时取消选择该单元格。我该如何实施?
谢谢!
全部,
我正在尝试实现一个破折号数据表,我通过直接单击它来选择行(没有单选按钮)。目前,我正在使用 执行此操作,active_cell并且效果很好:无论用户单击行的哪个单元格,都会使用该行中的数据更新图表。如果他单击同一行中的另一个单元格,则未选择数据(通过 dcc.storage)
我的问题来了:如果用户再次单击同一个单元格,则不会active_cell触发任何事件。因此,我的回调没有被触发,也没有任何反应。我想在用户第二次单击该单元格时取消选择该单元格。我该如何实施?
谢谢!
所以......我解决了这个......它并不漂亮但它有效 - 它包括一个我必须实施以避免循环依赖的loopbreaker,但是是的 - 我绝对愿意接受更清洁的解决方案。
在回调下方查找
# takes user selected cell (active_cell) and the current state of a dcc.storage (tableclick) which stores the last saved row that was clicked
# output: updated selected_rows for the datatable, styling for the selected row and update for dcc.storage
# if no cell is selected, do nothing
# if no cell is selected, but there is a row stored as selected, highlight that row (this is a consequence from the circular dependency)
# if a cell is selected that is different from the previous cell, highlight that new row. Otherwise, deselect the row.
@app.callback(
[Output('performancedatatable', 'style_data_conditional'), Output('tableclick', 'data'),
Output('performancedatatable', 'selected_rows')],
[
Input('performancedatatable', 'active_cell'),
], [State('tableclick', 'data')]
)
def highlight_row(cell, prevrow):
if cell is None:
if prevrow is None:
return [{}], None, []
else:
return [{}], None, prevrow
elif "row" in cell:
if cell.get("row", "") == prevrow:
return [{}], None, []
else:
return ([{
"if": {"row_index": cell.get("row", "")},
"backgroundColor": "rgba(146, 192, 234, 0.5)",
}], cell.get("row", ""), [cell.get("row", "")])
# Is triggered by changing the dcc.storage "tableclick"
# resets active cell and selected cell via callback below
@app.callback([Output('loopbreaker_div', "children")], [Input('tableclick', 'data')])
def reset_active_cell(input):
return [html.Div(id='loopbreaker', children=True)]
#loopbreaker to avoid circular dependency
@app.callback([Output('performancedatatable', "active_cell"), Output('performancedatatable', 'selected_cells')], [Input('loopbreaker', 'children')])
def reset_active_cell(input):
time.sleep(1)
return (None, [])
大喊http://yaaics.blogspot.com/2019/03/circular-references-in-plotlydash.html帮助解决循环依赖
一个更简单的解决方案(但它有其他缺点)是选择一个隐藏的单元格。这使用户觉得没有选择任何内容。
在下面的示例中,一个单元格由回调处理和取消选择。显然,此回调也可以用于“取消全选”按钮或您需要的任何其他内容。
添加名为“cant_see”的列:
df = pd.read_csv("my_data.csv")
df.insert(0, "cant_see", ["" for i in df.iloc[:, 0] ])
使用style_data_conditional和style_header_conditional创建 DataTable 时将其隐藏:
dash_table.DataTable(
id="table",
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict("records"),
is_focused=True,
style_data_conditional=[
{'if': {'column_id': 'cant_see',}, 'display': 'None',}
],
style_header_conditional=[
{'if': {'column_id': 'cant_see',}, 'display': 'None',}
],
)
然后回调可以设置表的“active_cell”和/或“selected_cells”
@app.callback(
Output("table", "active_cell"),
Output("table", "selected_cells"),
Input("table", "active_cell"),)
def cell_clicked(cell):
# Do something useful with cell,
# such as toggling it's style to mimic select/de-select
# Now make it look like the cell is de-selected
# by selecting a hidden cell
#
# return active cell 0,0 and selected_cells list [ 0,0 ]
return {'column':0, 'row':0}, [{'column':0, 'row':0}]