Use the scrollTo
prop to scroll to a specific position in the grid.
Requires dash-ag-grid>=2.2.0
scrollTo
is a dict with keys:
rowIndex
(number; optional): rowIndex, typically a row number, to scroll to.
rowId
(string; optional): Id of the row to scroll to.
data
(dict; optional): The rowData of the row to scroll to.
rowPosition
(“top” | “bottom” | “middle”; optional): Default “top”. If a position is provided, the grid will attempt to scroll until the row is at the given position within the viewport.
column
(string; optional): Ensures the column is visible by scrolling the grid horizontally if needed. Must be a field
in columnDefs
.
columnPosition
(“auto” | “start” | “middle” | “end”; optional): Default “auto”. Position of the column in the grid after scrolling.
NOTE: If any of rowIndex
, rowId
, and data
are passed to scrollTo
simultaneously only one of them will be used as all of them set the vertical scroll position.
The order of priority will be rowIndex
, then rowId
, and finally data
.
This example scrolls to the row index, typically the row number. You can also specify if the specified index should be at the top, middle or bottom of the viewport, and scroll horizontally to ensure that a column is visible.
import dash_ag_grid as dag
from dash import Dash, html, dcc, Input, Output, State, callback
import pandas as pd
import dash_bootstrap_components as dbc
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)
columnDefs = [
{"headerName": "Row", "valueGetter": {"function": "params.node.rowIndex", 'pinned': True}}
] + [{"field": c} for c in df.columns]
app.layout = dbc.Container(
[
dbc.Row(
[
dbc.Col(
[
dbc.Label("Row index"),
dbc.Input(
id="row-index-scroll-to",
type="number",
min=0,
max=df.shape[0] - 1,
step=1,
),
dbc.Label("Row Position"),
dcc.Dropdown(
options=["top", "bottom", "middle"],
id="row-position-scroll-to",
),
]
),
dbc.Col(
[
dbc.Label("Column"),
dcc.Dropdown(options=df.columns, id="column-scroll-to"),
dbc.Label("Column Position"),
dcc.Dropdown(
options=["auto", "start", "middle", "end"],
id="column-position-scroll-to",
),
]
),
],
className="mb-2",
),
dag.AgGrid(
id="grid-scroll-to",
columnDefs=columnDefs,
rowData=df.to_dict("records"),
columnSize="sizeToFit",
defaultColDef={"resizable": True, "sortable": True, "minWidth": 150},
),
html.Div(id="out-scroll-to"),
],
fluid=True,
)
@callback(
Output("out-scroll-to", "children"),
Input("grid-scroll-to", "scrollTo"),
)
def show_scroll(scroll):
return f"scroll_to = {str(scroll)}"
@callback(
Output("grid-scroll-to", "scrollTo"),
Input("row-index-scroll-to", "value"),
Input("column-scroll-to", "value"),
Input("row-position-scroll-to", "value"),
Input("column-position-scroll-to", "value"),
State("grid-scroll-to", "scrollTo"),
)
def scroll_to_row_and_col(row_index, column, row_position, column_position, scroll_to):
if not scroll_to:
scroll_to = {}
scroll_to["rowIndex"] = row_index
scroll_to["column"] = column
scroll_to["rowPosition"] = row_position
scroll_to["columnPosition"] = column_position
return scroll_to
if __name__ == "__main__":
app.run(debug=True)
This example will scroll vertically to a unique row id, rather than scrolling to a row number like the example above. Try sorting a column in each example to see the difference.
In this example we create a unique id using the index of the dataframe. See more
information the Row IDs section.
import dash_ag_grid as dag
from dash import Dash, html, dcc, Input, Output, State, callback
import pandas as pd
import dash_bootstrap_components as dbc
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)
df["id"] = df.index
columnDefs = [
{
"headerName": "Row #",
"valueGetter": {"function": "params.node.rowIndex"},
"width": 100,
"pinned": True
},
{"field": "id", "width": 75, "pinned": True},
] + [{"field": c} for c in df.columns if c != "id"]
app.layout = dbc.Container(
[
dbc.Row(
[
dbc.Col(
[
dbc.Label("Row id"),
dbc.Input(
id="row-scroll-to-id",
type="number",
min=0,
max=df.shape[0] - 1,
step=1,
),
dbc.Label("Position"),
dcc.Dropdown(
options=["top", "bottom", "middle"],
id="row-position-scroll-to-id",
),
]
),
dbc.Col(
[
dbc.Label("Column"),
dcc.Dropdown(options=df.columns, id="column-scroll-to-id"),
dbc.Label("Position"),
dcc.Dropdown(
options=["auto", "start", "middle", "end"],
id="column-position-scroll-to-id",
),
]
),
],
className="mb-2",
),
dag.AgGrid(
id="grid-scroll-to-id",
columnDefs=columnDefs,
rowData=df.to_dict("records"),
defaultColDef={"resizable": True, "sortable": True},
getRowId="params.data.id",
),
html.Div(id="out-scroll-to-id"),
],
fluid=True,
)
@callback(
Output("out-scroll-to-id", "children"),
Input("grid-scroll-to-id", "scrollTo"),
)
def show_scroll(scroll):
return f"scroll_to = {str(scroll)}"
@callback(
Output("grid-scroll-to-id", "scrollTo"),
Input("row-scroll-to-id", "value"),
Input("column-scroll-to-id", "value"),
Input("row-position-scroll-to-id", "value"),
Input("column-position-scroll-to-id", "value"),
State("grid-scroll-to-id", "scrollTo"),
)
def scroll_to_row_and_col(row_id, column, row_position, column_position, scroll_to):
if not scroll_to:
scroll_to = {}
scroll_to["rowId"] = str(row_id)
scroll_to["column"] = column
scroll_to["rowPosition"] = row_position
scroll_to["columnPosition"] = column_position
return scroll_to
if __name__ == "__main__":
app.run(debug=True)
Here we use the "data"
key in the scrollTo
prop to position the grid at a certain row.
Note the following:
- The data
must be a single row in the same format as rowData
- Since we are not specifying position of the row and columns in the viewport, the grid uses the defaults:
{"rowPosition":"top", "columnPosition": "auto"}
import dash_ag_grid as dag
from dash import Dash, dcc, html, Input, Output, callback, no_update
import pandas as pd
app = Dash(__name__)
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)
df = df.sort_values(by=["year", "country"])
rowData = df.to_dict("records")
app.layout = html.Div(
[
html.Label("Scroll to start of year:"),
dcc.Dropdown(df.year.unique(), id="dd-scroll-to-data", style={"width": 200}),
dag.AgGrid(
id="grid-scroll-to-data",
columnDefs=[{"field": c} for c in df.columns],
rowData=rowData,
defaultColDef={"resizable": True},
),
html.Div(id="out-scroll-to-data"),
]
)
@callback(
Output("out-scroll-to-data", "children"),
Input("grid-scroll-to-data", "scrollTo"),
)
def show_scroll(scroll):
return f"scroll_to = {str(scroll)}"
@callback(
Output("grid-scroll-to-data", "scrollTo"),
Input("dd-scroll-to-data", "value"),
prevent_initial_call=True,
)
def scroll_to_data(value):
if value is None:
return no_update
for row in rowData:
if row["year"] == value:
break
return {"data": row}
if __name__ == "__main__":
app.run_server(debug=True)
It’s possible to specify the initial Scroll To position when the app starts. This example sets the scrollTo
prop in
the grid definition, here to start at row number 100, rather than only in a callback:
grid = dag.AgGrid(
scrollTo={"rowIndex": 100},
# other props
)
import dash_ag_grid as dag
from dash import Dash, html
import pandas as pd
app = Dash(__name__)
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)
columnDefs = [
{"headerName": "Row", "valueGetter": {"function": "params.node.rowIndex"}}
] + [{"field": c} for c in df.columns]
app.layout = html.Div(
[
dag.AgGrid(
id="grid-scroll-to-start",
columnDefs=columnDefs,
rowData=df.to_dict("records"),
defaultColDef={"resizable": True, "sortable": True},
scrollTo={"rowIndex": 100},
),
]
)
if __name__ == "__main__":
app.run(debug=True)
In order to scroll to a position, the row must exist the DOM. When using pagination, only rows on the current
page exist. To scroll to a row on a different page, the grid must be on that page prior to setting the scrollTo
prop.
In this example we use a clientside callback to calculate which page the row is located and the paginationGoToPage
function to show the page. Note that it goes to the correct page based on the current state of the grid, including sort and/or filters applied.
import dash_ag_grid as dag
from dash import Dash, dcc, html, Input, Output, clientside_callback
import pandas as pd
app = Dash(__name__)
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)
df["id"] = df.index
columnDefs = [
{
"headerName": "Row #",
"valueGetter": {"function": "params.node.rowIndex"},
"width": 100,
},
{"field": "id", "width": 75},
] + [{"field": c} for c in df.columns if c != "id"]
app.layout = html.Div(
[
html.Label("Scroll to row id:"),
dcc.Input(id="input-scroll-to-pagination", min=0, max=df.shape[0], type="number"),
dag.AgGrid(
id="grid-scroll-to-pagination",
columnDefs=columnDefs,
rowData=df.to_dict("records"),
defaultColDef={"resizable": True, "sortable": True},
getRowId="params.data.id",
dashGridOptions={"pagination": True, "paginationPageSize": 50},
),
]
)
clientside_callback(
"""function (rowId) {
if (rowId) {
grid = dash_ag_grid.getApi("grid-scroll-to-pagination")
rowIndex = grid.getRowNode(rowId).rowIndex
pageTarget = Math.floor(rowIndex / grid.paginationGetPageSize())
grid.paginationGoToPage(pageTarget)
}
return {"rowId": rowId.toString()}
}""",
Output("grid-scroll-to-pagination", "scrollTo"),
Input("input-scroll-to-pagination", "value"),
prevent_initial_call=True,
)
if __name__ == "__main__":
app.run(debug=True)
The scrollTo
prop works with both the clientside and serverside row models. Here is an example with the Infinite Row Model.
import dash_ag_grid as dag
from dash import Dash, Input, Output, dcc, html, no_update, callback
import pandas as pd
app = Dash(__name__)
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)
columnDefs = [
# this column shows the row index, doesn't use any data from the row
{
"headerName": "ID",
"maxWidth": 100,
# it is important to have node.id here, so that when the id changes (which happens
# when the row is loaded) then the cell is refreshed.
"valueGetter": {"function": "params.node.id"},
},
{"field": "athlete", "minWidth": 150},
{"field": "country", "minWidth": 150},
{"field": "year"},
{"field": "sport", "minWidth": 150},
{"field": "total"},
]
defaultColDef = {
"flex": 1,
"sortable": False,
"resizable": True,
}
app.layout = html.Div(
[
dcc.Markdown("Infinite scroll: No sorting or filtering"),
html.Label("Scroll to row id:"),
dcc.Input(id="input-scroll-to-infinite", min=0, max=df.shape[0], type="number"),
dag.AgGrid(
id="grid-scroll-to-infinite",
columnDefs=columnDefs,
defaultColDef=defaultColDef,
rowModelType="infinite",
dashGridOptions={
# The number of rows rendered outside the viewable area the grid renders.
"rowBuffer": 0,
# How many blocks to keep in the store. Default is no limit, so every requested block is kept.
"maxBlocksInCache": 10,
"cacheBlockSize": 100,
"cacheOverflowSize": 2,
"maxConcurrentDatasourceRequests": 1,
"infiniteInitialRowCount": 1000,
},
),
],
)
@callback(
Output("grid-scroll-to-infinite", "scrollTo"),
Input("input-scroll-to-infinite", "value"),
)
def scroll_to_infinite(value):
return {"rowIndex": value}
@callback(
Output("grid-scroll-to-infinite", "getRowsResponse"),
Input("grid-scroll-to-infinite", "getRowsRequest"),
)
def infinite_scroll(request):
if request is None:
return no_update
partial = df.iloc[request["startRow"] : request["endRow"]]
return {"rowData": partial.to_dict("records"), "rowCount": len(df.index)}
if __name__ == "__main__":
app.run(debug=True)
Infinite scroll: No sorting or filtering
As with pagination, when using Row Groups (an AG Grid Enterprise feature), the row group must be expanded prior to setting the scrollTo
prop.
See an example in the Scroll To With Row Groups example in the Enterprise section.