plotly/dash-ag-grid

Pagination and scrollTo interaction gives incorrect results.

Closed this issue · 5 comments

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.

Screen.Recording.2023-07-21.at.11.09.05.AM.mp4
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

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.

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

BSd3v commented

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

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

BSd3v commented
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.