Pinned rows appear either above or below the normal rows of a table. This is sometimes also known as Frozen Rows or Floating Rows. Rows can be pinned via the Context Menu or Grid Options.
Enabling Row Pinning Copy Link
To enable row pinning, set enableRowPinning to true. To restrict pinning to only one direction, set it to 'top' or 'bottom'.
const enableRowPinning = true;
<AgGridReact enableRowPinning={enableRowPinning} /> Pinning Rows on First Render Copy Link
To have a row appear as pinned when the grid initially renders data, use the isRowPinned callback. Returning 'top' or 'bottom' from this callback will pin the row to the top or bottom respectively, and returning null or undefined will leave the row unpinned. As an example, the snippet below will pin all rows whose country field is null in the top container, and all the other rows will be unpinned.
const enableRowPinning = true;
const isRowPinned = (rowNode) => {
return rowNode.data?.country == null ? 'top' : null;
};
<AgGridReact
enableRowPinning={enableRowPinning}
isRowPinned={isRowPinned}
/>This is illustrated in the example below. Rows that are pinned appear fixed at the top (or bottom) of the grid, as well as remaining in the main viewport. Pinned rows are styled bold by default to visually distinguish them.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
IsRowPinned,
ModuleRegistry,
PinnedRowModule,
Theme,
enableDevValidations,
themeQuartz,
} from "ag-grid-community";
import { ContextMenuModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
const modules = [ClientSideRowModelModule, ContextMenuModule, PinnedRowModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "athlete" },
{ field: "country" },
{ field: "sport" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
};
}, []);
const isRowPinned = useCallback((rowNode) => {
return rowNode.data?.country == null ? "top" : null;
}, []);
const theme = useMemo<Theme | "legacy">(() => {
return themeQuartz.withParams({
pinnedRowBorder: {
width: 2,
},
});
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/small-olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
enableRowPinning={true}
isRowPinned={isRowPinned}
theme={theme}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
setData(data);
setLoading(false);
};
fetchData();
}, [url, limit]);
return { data, loading };
}; Note that all the examples on this page also apply additional styling to visually separate the pinned rows from the rows in the main viewport.
const theme = themeQuartz.withParams({
pinnedRowBorder: {
width: 2
},
});
<AgGridReact theme={theme} />To see what other parameters are available for the theming of pinned rows, see the Theme Builder.
Pinning Rows via the Context Menu Copy Link
This approach requires the Context Menu which is an Enterprise feature.
To pin a row, use right-click to bring up the Context Menu and select one of the options in the "Pin Row" submenu. In the example below, try the following:
- Pin a row to the top.
- Switch the row to being pinned to the bottom.
- Unpin the row.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
PinnedRowModule,
Theme,
enableDevValidations,
themeQuartz,
} from "ag-grid-community";
import { ContextMenuModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
const modules = [PinnedRowModule, ClientSideRowModelModule, ContextMenuModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "athlete" },
{ field: "country" },
{ field: "sport" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
};
}, []);
const theme = useMemo<Theme | "legacy">(() => {
return themeQuartz.withParams({
pinnedRowBorder: {
width: 2,
},
});
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/small-olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
enableRowPinning={true}
theme={theme}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
setData(data);
setLoading(false);
};
fetchData();
}, [url, limit]);
return { data, loading };
}; Preventing Rows from being Pinnable Copy Link
To prevent a user from pinning a row via the context menu, use the isRowPinnable callback. As an example, the snippet below will prevent any rows being pinned where the sport field is 'Swimming'.
const enableRowPinning = true;
const isRowPinnable = (rowNode) => {
return rowNode.data?.sport != 'Swimming';
};
<AgGridReact
enableRowPinning={enableRowPinning}
isRowPinnable={isRowPinnable}
/>This is illustrated in the example below. Note that the "Pin Rows" submenu does not appear in the context menu for rows whose sport field is 'Swimming'.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
IsRowPinnable,
ModuleRegistry,
PinnedRowModule,
Theme,
enableDevValidations,
themeQuartz,
} from "ag-grid-community";
import { ClipboardModule, ContextMenuModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
const modules = [
PinnedRowModule,
ClientSideRowModelModule,
ContextMenuModule,
ClipboardModule,
];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "athlete" },
{ field: "country" },
{ field: "sport" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
};
}, []);
const isRowPinnable = useCallback((rowNode) => {
return rowNode.data?.sport != "Swimming";
}, []);
const theme = useMemo<Theme | "legacy">(() => {
return themeQuartz.withParams({
pinnedRowBorder: {
width: 2,
},
});
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/small-olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
enableRowPinning={true}
isRowPinnable={isRowPinnable}
theme={theme}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
setData(data);
setLoading(false);
};
fetchData();
}, [url, limit]);
return { data, loading };
}; Sorting and Filtering Pinned Rows Copy Link
When sorts and filters are applied to the grid, they will also be applied to pinned rows.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
ColumnApiModule,
GridApi,
GridOptions,
GridReadyEvent,
IsRowPinned,
ModuleRegistry,
PinnedRowModule,
Theme,
enableDevValidations,
themeQuartz,
} from "ag-grid-community";
import { ContextMenuModule, SetFilterModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
const modules = [
PinnedRowModule,
ClientSideRowModelModule,
ContextMenuModule,
SetFilterModule,
ColumnApiModule,
];
function filterSwimming(api: GridApi<IOlympicData>) {
api
.setColumnFilterModel("sport", { values: ["Swimming"] })
.then(() => api.onFilterChanged());
}
function sortGold(api: GridApi<IOlympicData>) {
api.applyColumnState({ state: [{ colId: "gold", sort: "desc" }] });
}
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [rowData, setRowData] = useState<IOlympicData[]>();
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "athlete" },
{ field: "country" },
{ field: "sport", filter: true, floatingFilter: true },
{ field: "gold" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
};
}, []);
const isRowPinned = useCallback(
(node) => (!node.data?.country ? "top" : null),
[],
);
const theme = useMemo<Theme | "legacy">(() => {
return themeQuartz.withParams({
pinnedRowBorder: {
width: 2,
},
});
}, []);
const onGridReady = useCallback((params: GridReadyEvent) => {
fetch("https://www.ag-grid.com/example-assets/small-olympic-winners.json")
.then((resp) => resp.json())
.then((data: IOlympicData[]) => {
setRowData(data);
filterSwimming(params.api);
sortGold(params.api);
});
}, []);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={rowData}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
enableRowPinning={true}
isRowPinned={isRowPinned}
theme={theme}
onGridReady={onGridReady}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} Selecting Pinned Rows Copy Link
Pinned rows can be selected just as normal rows can be selected. The selection state of a pinned row will mirror the selection state of the original row.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
IsRowPinned,
ModuleRegistry,
PinnedRowModule,
RowApiModule,
RowSelectionModule,
RowSelectionOptions,
Theme,
enableDevValidations,
themeQuartz,
} from "ag-grid-community";
import { ContextMenuModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
const modules = [
ClientSideRowModelModule,
PinnedRowModule,
RowSelectionModule,
RowApiModule,
ContextMenuModule,
];
const GridExample = () => {
const gridRef = useRef<AgGridReact<IOlympicData>>(null);
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "athlete" },
{ field: "country" },
{ field: "sport" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
};
}, []);
const isRowPinned = useCallback(
(node) => (!node.data?.country ? "top" : null),
[],
);
const rowSelection = useMemo<
RowSelectionOptions | "single" | "multiple"
>(() => {
return {
mode: "multiRow",
};
}, []);
const theme = useMemo<Theme | "legacy">(() => {
return themeQuartz.withParams({
pinnedRowBorder: {
width: 2,
},
});
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/small-olympic-winners.json",
);
const onFirstDataRendered = useCallback(() => {
["1", "3", "5"].forEach((id) => {
gridRef.current!.api.getRowNode(id)?.setSelected(true);
});
}, []);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
ref={gridRef}
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
enableRowPinning={true}
isRowPinned={isRowPinned}
rowSelection={rowSelection}
theme={theme}
onFirstDataRendered={onFirstDataRendered}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
setData(data);
setLoading(false);
};
fetchData();
}, [url, limit]);
return { data, loading };
}; Pinning the Grand Total Row Copy Link
The Grand Total Rows can be pinned in three ways.
- Setting the value of the
grandTotalRowgrid option to either'pinnedTop'or'pinnedBottom'. - Manually pin the grand total row via the context menu when
grandTotalRowis either'top'or'bottom'. - Return
'top'or'bottom'from theisRowPinnedcallback when it's called on the grand total row node.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import "./style.css";
import {
AutoGroupColumnDef,
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
PinnedRowModule,
RowPinnedType,
Theme,
enableDevValidations,
themeQuartz,
} from "ag-grid-community";
import { ContextMenuModule, RowGroupingModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
const modules = [
ClientSideRowModelModule,
RowGroupingModule,
ContextMenuModule,
PinnedRowModule,
];
function getGrandTotalRow() {
return document.querySelector<HTMLSelectElement>("#select-grand-total-row")
?.value as GridOptions["grandTotalRow"] | "isRowPinned";
}
function setGrandTotalRow(
api: GridApi<IOlympicData>,
value: GridOptions["grandTotalRow"],
) {
api.setGridOption("grandTotalRow", value);
}
function setIsRowPinned(api: GridApi<IOlympicData>, value: RowPinnedType) {
api.setGridOption("isRowPinned", (node) => {
if (node.level === -1 && node.footer) {
return value;
}
});
}
const GridExample = () => {
const gridRef = useRef<AgGridReact<IOlympicData>>(null);
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "athlete" },
{ field: "country", rowGroup: true, hide: true },
{ field: "sport" },
{ field: "gold", aggFunc: "sum" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
};
}, []);
const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
return {
headerName: "Country",
};
}, []);
const theme = useMemo<Theme | "legacy">(() => {
return themeQuartz.withParams({
pinnedRowBorder: {
width: 2,
},
});
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/small-olympic-winners.json",
);
const onFirstDataRendered = useCallback(() => {
const value = getGrandTotalRow();
if (value === "isRowPinned") {
setGrandTotalRow(gridRef.current!.api, "bottom");
setIsRowPinned(gridRef.current!.api, "top");
} else {
setGrandTotalRow(gridRef.current!.api, value);
}
}, []);
const update = useCallback(() => {
const value = getGrandTotalRow();
if (value === "isRowPinned") {
setGrandTotalRow(gridRef.current!.api, "bottom");
setIsRowPinned(gridRef.current!.api, "top");
} else {
setGrandTotalRow(gridRef.current!.api, value);
}
}, []);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div className="example-wrapper">
<div className="example-header">
<select id="select-grand-total-row" onChange={update}>
<option value="pinnedBottom">pinnedBottom</option>
<option value="pinnedTop">pinnedTop</option>
<option value="bottom">bottom</option>
<option value="top">top</option>
<option value="isRowPinned">isRowPinned</option>
</select>
</div>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
ref={gridRef}
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
autoGroupColumnDef={autoGroupColumnDef}
enableRowPinning={true}
theme={theme}
onFirstDataRendered={onFirstDataRendered}
/>
</div>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
.example-wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
.example-header {
margin-bottom: 10px;
}
#myGrid {
flex: 1 1 0px;
width: 100%;
}
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
setData(data);
setLoading(false);
};
fetchData();
}, [url, limit]);
return { data, loading };
}; Note that when grandTotalRow is 'pinnedTop' or 'pinnedBottom' the user is not able to unpin the grand total row.
Providing Pinned Row Data Copy Link
You cannot provide pinned row data at the same time as using enableRowPinning to manually pin rows.
Pinned row data may be provided directly to the grid via Grid Options. Providing pinned rows this way means they cannot be altered by end users.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
PinnedRowModule,
Theme,
enableDevValidations,
themeQuartz,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
const modules = [PinnedRowModule, ClientSideRowModelModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "athlete" },
{ field: "country" },
{ field: "sport" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
};
}, []);
const theme = useMemo<Theme | "legacy">(() => {
return themeQuartz.withParams({
pinnedRowBackgroundColor:
"color-mix(in srgb, var(--ag-background-color), #ffeb3b 18%)",
});
}, []);
const pinnedTopRowData = useMemo<any[]>(() => {
return [
{
athlete: "TOP (athlete)",
country: "TOP (country)",
sport: "TOP (sport)",
},
];
}, []);
const pinnedBottomRowData = useMemo<any[]>(() => {
return [
{
athlete: "BOTTOM (athlete)",
country: "BOTTOM (country)",
sport: "BOTTOM (sport)",
},
];
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
theme={theme}
pinnedTopRowData={pinnedTopRowData}
pinnedBottomRowData={pinnedBottomRowData}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
setData(data);
setLoading(false);
};
fetchData();
}, [url, limit]);
return { data, loading };
}; Set Pinned Rows using grid attributes pinnedTopRowData and pinnedBottomRowData.
Data to be displayed as pinned top rows in the grid. |
Data to be displayed as pinned bottom rows in the grid. |
Unsupported Features Copy Link
When providing pinned row data directly via pinnedTopRowData and pinnedBottomRowData, the following are not possible:
- Sorting: Pinned rows cannot be sorted.
- Filtering: Pinned rows are not filtered.
- Row Grouping: Pinned rows cannot be grouped.
- Row Selection: Pinned rows cannot be selected.
API Reference Copy Link
The pinned row state can be saved and restored as part of Grid State.
Determines whether manual row pinning is enabled via the row context menu.
Set to true to allow pinning rows to top or bottom.
Set to 'top' to allow pinning rows to the top only.
Set to 'bottom' to allow pinning rows to the bottom only. |
Return true if the grid should allow the row to be manually pinned.
Return false if the grid should prevent the row from being pinned
When not defined, all rows default to pinnable. |
Called for every row in the grid.
Return "top", "bottom" if the row should be initially pinned to the top or bottom respectively.
Return null or undefined otherwise.
User interactions can subsequently still change the pinned state of a row. |
Events Copy Link
A row has been pinned to top or bottom, or unpinned. |