plotly / dash-ag-grid

Dash AG Grid is a high-performance and highly customizable component that wraps AG Grid, designed for creating rich datagrids.
https://dash.plotly.com/dash-ag-grid
MIT License
165 stars 24 forks source link

Pagination and scrollTo interaction gives incorrect results. #222

Closed apberesford closed 11 months ago

apberesford commented 11 months ago

When pagination is enabled on an AGGrid, scrollTo behaves in an unexpected way. If the row exists but is on a different page, the scrollTo fires and goes to the end of the current page, displaying a row which is not the one the user was meant to be sent to. Reproducible with the code below.

Similar to issue #221, but it actually redirects the user to an incorrect row. Video below shows the first, successful attempt with pagination disabled.

https://github.com/plotly/dash-ag-grid/assets/107502692/d599f7e0-f1a3-43ad-b16b-966b1db5a549


import dash
from dash import html, dcc, callback, Output, Input
import pandas as pd

app = dash.Dash(__name__)

df = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)

columnDefs = [
    {"field": "country", "sortable": True, "filter": True},
    {"field": "year", "sortable": True, "filter": True},
    {"field": "athlete", "sortable": True, "filter": True},
    {"field": "age", "sortable": True, "filter": True},
    {"field": "date", "sortable": True, "filter": True},
    {"field": "sport", "sortable": True, "filter": True},
    {"field": "total", "sortable": True, "filter": True},
]

app.layout = html.Div(
    [
        dag.AgGrid(
            columnDefs=columnDefs,
            rowData=df.to_dict("records"),
            # AG Grid is showing only 50 rows per page
            dashGridOptions={
                "pagination": True,
                "paginationPageSize": 50,
                "rowSelection": "single",
            },
            defaultColDef=dict(
                resizable=True,
            ),
            id="grouped-grid",
            enableEnterpriseModules=True,
            licenseKey="LICENSE_KEY_HERE",
            getRowId="params.data.date+params.data.athlete",
        ),
        html.Button("Scroll to index Matt Grevers 24/08/2008", id="button"),
    ]
)

@callback(
    Output("grouped-grid", "scrollTo"),
    Input("button", "n_clicks"),
    prevent_initial_call=True,
)
def scroll_to(n_clicks):
    return {"rowId": "24/08/2008Matt Grevers"}

if __name__ == "__main__":
    app.run_server(debug=True)```
BSd3v commented 11 months ago

Hello @apberesford,

Like in the issue that you mentioned, you as the dev need to know that this is the case, and check to make sure that the row exists inside the page.

The node exposure finds the row where it is supposed to be placed in the page, thus triggering the event to go there.

apberesford commented 11 months ago

Hi @BSd3v Perfect that's good to know. In that case can I tag this with docs also?

BSd3v commented 11 months ago

I'm not entirely sure how to go about getting to the proper page, the rowNode says that it is displayed, and doesnt return what page it is currently listed

AnnMarieW commented 11 months ago

Wouldn't it be better just use the filters to view the rows with that data?

BSd3v commented 11 months ago
import dash
from dash import html, dcc, callback, Output, Input
import pandas as pd
import dash_ag_grid as dag

app = dash.Dash(__name__)

df = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)

columnDefs = [
    {"field": "country", "sortable": True, "filter": True},
    {"field": "year", "sortable": True, "filter": True},
    {"field": "athlete", "sortable": True, "filter": True},
    {"field": "age", "sortable": True, "filter": True},
    {"field": "date", "sortable": True, "filter": True},
    {"field": "sport", "sortable": True, "filter": True},
    {"field": "total", "sortable": True, "filter": True},
]

app.layout = html.Div(
    [
        dag.AgGrid(
            columnDefs=columnDefs,
            rowData=df.to_dict("records"),
            # AG Grid is showing only 50 rows per page
            dashGridOptions={
                "pagination": True,
                "paginationPageSize": 50,
                "rowSelection": "single",
            },
            defaultColDef=dict(
                resizable=True,
            ),
            id="grouped-grid",
            getRowId="params.data.date+params.data.athlete",
        ),
        html.Button("Scroll to index Matt Grevers 24/08/2008", id="button"),
    ]
)

app.clientside_callback(
    """function (n) {
        const exposeRow = (rowId, id) => {
            grid = dash_ag_grid.getApi(id)
            rowIndex = grid.getRowNode(rowId).rowIndex
            pageTarget = Math.floor(rowIndex / grid.paginationGetPageSize())
            grid.paginationGoToPage(pageTarget)
        }
        exposeRow("24/08/2008Matt Grevers", "grouped-grid")
        return {"rowId": "24/08/2008Matt Grevers"}
    }""",
    Output("grouped-grid", "scrollTo"),
    Input("button", "n_clicks"),
    prevent_initial_call=True,
)

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

The rowNode returns the rowIndex, which we can use to determine the page by comparing the page size it is currently on.