plotly / dash-table

OBSOLETE: now part of https://github.com/plotly/dash
https://dash.plotly.com
MIT License
420 stars 74 forks source link

Python backend sorting and filtering while keeping row selections functionality #938

Open ammaar8 opened 2 years ago

ammaar8 commented 2 years ago

Hey folks, We have a use case where we need to use backend filtering and sorting since our data in some columns is a mix of Strings and Ints. The given examples work well if we only need to filter and/or sort. The issue is we also need to keep row selections. The row selections break since the data is changing. Does anyone know how we can do this? Is there a work around? I though of using derived_virtual_data but it seems to be read only and would need us to set all the other derived properties too?

alexcjohnson commented 2 years ago

In principle row IDs should make this work right, but I wouldn't be surprised if there are bugs. If you want to post a complete standalone example that reproduces a bug we can look into it.

AnnMarieW commented 2 years ago

Here is a MWE based on the "Backend Paging With Sorting" example from the docs. It just has row_selectable='multi' added to the table definition.

Also, #924 has a good MWE for some additional bugs with selected_rows when data is updated with a callback. The first example in #924 was fixed in #907, but I can verify that the other items are still issues.

from dash import Dash, Input, Output, dash_table

import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminder2007.csv')

df[' index'] = range(1, len(df) + 1)

app = Dash(__name__)

PAGE_SIZE = 5

app.layout = dash_table.DataTable(
    id='table-paging-and-sorting',
    columns=[
        {'name': i, 'id': i, 'deletable': True} for i in sorted(df.columns)
    ],
    page_current=0,
    page_size=PAGE_SIZE,
    page_action='custom',

    sort_action='custom',
    sort_mode='single',
    sort_by=[],
    row_selectable='multi'
)

@app.callback(
    Output('table-paging-and-sorting', 'data'),
    Input('table-paging-and-sorting', "page_current"),
    Input('table-paging-and-sorting', "page_size"),
    Input('table-paging-and-sorting', 'sort_by'))
def update_table(page_current, page_size, sort_by):
    if len(sort_by):
        dff = df.sort_values(
            sort_by[0]['column_id'],
            ascending=sort_by[0]['direction'] == 'asc',
            inplace=False
        )
    else:
        # No sort is applied
        dff = df

    return dff.iloc[
        page_current*page_size:(page_current+ 1)*page_size
    ].to_dict('records')

if __name__ == '__main__':
    app.run_server(debug=True)

table