I decided to take a different approach and I’m posting it here in case someone else finds it useful. I created a separate table that stores the selected row of the main table. The main table can then use backend paging, sorting, and filtering retaining it’s responsiveness, and the table of selected row can ignore the filters and sorting of the main table. It works well for my application.
import dash
import dash_html_components as html
from dash.dependencies import Input, Output, State
import dash_table
import pandas as pd
df = pd.DataFrame({'id': [0,1,2,3,4,5,6,7,8], 'A': ['a','b','c','d','e','f','g','h','i'], 'B': [11,12,13,14,5,16,17,18,19]})
app = dash.Dash(__name__)
PAGE_SIZE = 3
app.layout = html.Div([dash_table.DataTable(
id='table-paging-and-sorting',
columns=[{'name': i, 'id': i} for i in sorted(df.columns) if i != 'id'],
page_current=0,
page_size=PAGE_SIZE,
page_action='custom',
sort_action='custom',
sort_mode='single',
sort_by=[],
row_selectable = 'multi',
selected_rows = []
),
html.H1('Selected'),
dash_table.DataTable(
id='table-selected',
columns=[{'name': i, 'id': i} for i in sorted(df.columns) if i != 'id'],
page_action='native',
sort_action='native',
sort_mode='single',
row_deletable = True,
sort_by=[],
)],
style = {'width': '20%'})
@app.callback(
Output('table-paging-and-sorting', 'data'),
[Input('table-paging-and-sorting', "page_current"),
Input('table-paging-and-sorting', 'sort_by')],
[State('table-paging-and-sorting', "page_size")])
def update_table(page_current, sort_by, page_size):
app.logger.info(f"update_table page_current:{page_current} sort_by:{sort_by} page_size:{page_size}")
if len(sort_by):
dff = df.sort_values(sort_by[0]['column_id'], ascending=sort_by[0]['direction'] == 'asc', inplace=False)
else:
dff = df
return dff.iloc[page_current*page_size:(page_current+ 1)*page_size].to_dict('records')
@app.callback(
Output('table-selected', 'data'),
[Input('table-paging-and-sorting', 'selected_row_ids')],
[State('table-selected', 'data')])
def update_selection(selected_row_ids, data_current):
app.logger.info(f"update_selection selected_row_ids:{selected_row_ids} data_current:{data_current}")
if selected_row_ids is not None and len(selected_row_ids) > 0:
data_new = df[df.id.isin(selected_row_ids)].to_dict('records')
if data_current is not None:
ids = [r['id'] for r in data_current]
for r in data_new:
if r['id'] not in ids:
data_current.append(r)
else:
data_current = data_new
return data_current
if __name__ == '__main__':
app.run_server(debug=True, host = '0.0.0.0')