This section covers how to configure the Side Bar which contains Tool Panels.
Configuring the Side Bar Copy Link
The Side Bar is configured using the grid property sideBar. The property takes multiple forms to allow easy configuration or more advanced configuration. The different forms for the sideBar property are as follows:
| Type | Description |
|---|---|
undefined / null | No Side Bar provided. |
boolean | Set to true to display the Side Bar with default configuration. |
string / string[] | Set to 'columns', 'filters' or 'filters-new' to display the Side Bar with just one of Columns, Filters or New Filters Tool Panels or an array of some or all of these values. |
SideBarDef(long form) | An object of type SideBarDef (explained below) to allow detailed configuration of the Side Bar. Use this to configure the provided Tool Panels (e.g. pass parameters to the columns or filters panel) or to include custom Tool Panels. |
Boolean Configuration Copy Link
The default Side Bar contains the Columns and Filters Tool Panels. To use the default Side Bar, set the grid property sideBar=true. The Columns panel will be open by default.
The default configuration doesn't allow customisation of the Tool Panels.
"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 {
AutoGroupColumnDef,
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
NumberFilterModule,
SideBarDef,
TextFilterModule,
enableDevValidations,
} from "ag-grid-community";
import {
ColumnsToolPanelModule,
FiltersToolPanelModule,
PivotModule,
SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [
NumberFilterModule,
ClientSideRowModelModule,
ColumnsToolPanelModule,
FiltersToolPanelModule,
SetFilterModule,
PivotModule,
TextFilterModule,
];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "athlete", filter: "agTextColumnFilter", minWidth: 200 },
{ field: "age" },
{ field: "country", minWidth: 180 },
{ field: "year" },
{ field: "date", minWidth: 150 },
{ field: "gold" },
{ field: "silver" },
{ field: "bronze" },
{ field: "total" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
// allow every column to be aggregated
enableValue: true,
// allow every column to be grouped
enableRowGroup: true,
// allow every column to be pivoted
enablePivot: true,
filter: true,
};
}, []);
const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
return {
minWidth: 200,
};
}, []);
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}
autoGroupColumnDef={autoGroupColumnDef}
sideBar={true}
/>
</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(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
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;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; String Configuration Copy Link
To display just one of the provided Tool Panels, set either sideBar='columns', sideBar='filters' or sideBar='filters-new'. This will display the desired item with default configuration. Alternatively pass some or all of these values as a string[], i.e sideBar=['columns','filters', 'filters-new'].
The example below demonstrates using the string configuration. Note the following:
- The grid property
sideBaris set to'filters'. - The Side Bar is displayed showing only the Filters panel.
"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,
NumberFilterModule,
SideBarDef,
TextFilterModule,
enableDevValidations,
} from "ag-grid-community";
import {
ColumnsToolPanelModule,
FiltersToolPanelModule,
PivotModule,
SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [
NumberFilterModule,
ClientSideRowModelModule,
ColumnsToolPanelModule,
FiltersToolPanelModule,
SetFilterModule,
PivotModule,
TextFilterModule,
];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "athlete", filter: "agTextColumnFilter", minWidth: 200 },
{ field: "age" },
{ field: "country", minWidth: 180 },
{ field: "year" },
{ field: "date", minWidth: 150 },
{ field: "gold" },
{ field: "silver" },
{ field: "bronze" },
{ field: "total" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
// allow every column to be aggregated
enableValue: true,
// allow every column to be grouped
enableRowGroup: true,
// allow every column to be pivoted
enablePivot: true,
filter: true,
};
}, []);
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}
sideBar={"filters"}
/>
</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(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
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;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; SideBarDef Configuration Copy Link
The previous configurations are shortcuts for the full fledged configuration using a SideBarDef object. For full control over the configuration, you must provide a SideBarDef object.
Properties available on the SideBarDef interface.
A list of all the panels to place in the side bar. The panels will be displayed in the provided order from top to bottom.
|
The panel (identified by ID) to open by default. If none specified, the side bar is initially displayed closed. |
To hide the side bar by default, set this to true. If left undefined the side bar will be shown. |
Sets the side bar position relative to the grid. |
To hide the side bar buttons by default set this to true. If left undefined the buttons will be shown. This is useful if you want to show a tool panel without showing the buttons. |
The toolPanels property follows the ToolPanelDef interface:
Properties available on the ToolPanelDef interface.
The unique ID for this panel. Used in the API and elsewhere to refer to the panel. |
The key used for localisation for displaying the label. The label is displayed in the tab button. |
The default label if labelKey is missing or does not map to valid text through localisation. |
The min width of the tool panel. |
The max width of the tool panel. |
The initial width of the tool panel. |
The key of the icon to be used as a graphical aid beside the label in the side bar. |
The tool panel component to use as the panel. The provided panels use components agColumnsToolPanel, agFiltersToolPanel and agNewFiltersToolPanel. To provide your own custom panel component, you reference it here.
|
Customise the parameters provided to the toolPanel component. |
DOM element to use as the parent for the tool panel to allow it to appear outside the grid. Set to null or omit the property for tool panel to appear inside the grid.
|
The following snippet shows configuring the Tool Panel using a SideBarDef object:
const sideBar = useMemo(() => {
return {
toolPanels: [
{
id: 'columns',
labelDefault: 'Columns',
labelKey: 'columns',
iconKey: 'columns',
toolPanel: 'agColumnsToolPanel',
minWidth: 225,
maxWidth: 225,
width: 225
},
{
id: 'filters',
labelDefault: 'Filters',
labelKey: 'filters',
iconKey: 'filter',
toolPanel: 'agFiltersToolPanel',
minWidth: 180,
maxWidth: 400,
width: 250
}
],
position: 'left',
defaultToolPanel: 'filters',
};
}, []);
<AgGridReact sideBar={sideBar} />The snippet above is demonstrated in the following example:
"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 {
AutoGroupColumnDef,
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
NumberFilterModule,
SideBarDef,
TextFilterModule,
enableDevValidations,
} from "ag-grid-community";
import {
ColumnsToolPanelModule,
FiltersToolPanelModule,
PivotModule,
SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [
NumberFilterModule,
ClientSideRowModelModule,
ColumnsToolPanelModule,
FiltersToolPanelModule,
SetFilterModule,
PivotModule,
TextFilterModule,
];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "athlete", filter: "agTextColumnFilter", minWidth: 200 },
{ field: "age" },
{ field: "country", minWidth: 180 },
{ field: "year" },
{ field: "date", minWidth: 150 },
{ field: "gold" },
{ field: "silver" },
{ field: "bronze" },
{ field: "total" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
// allow every column to be aggregated
enableValue: true,
// allow every column to be grouped
enableRowGroup: true,
// allow every column to be pivoted
enablePivot: true,
filter: true,
};
}, []);
const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
return {
minWidth: 200,
};
}, []);
const sideBar = useMemo<
SideBarDef | string | string[] | boolean | null
>(() => {
return {
toolPanels: [
{
id: "columns",
labelDefault: "Columns",
labelKey: "columns",
iconKey: "columns",
toolPanel: "agColumnsToolPanel",
minWidth: 225,
width: 225,
maxWidth: 225,
},
{
id: "filters",
labelDefault: "Filters",
labelKey: "filters",
iconKey: "filter",
toolPanel: "agFiltersToolPanel",
minWidth: 180,
maxWidth: 400,
width: 250,
},
],
position: "left",
defaultToolPanel: "filters",
};
}, []);
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}
autoGroupColumnDef={autoGroupColumnDef}
sideBar={sideBar}
/>
</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(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
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;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; Calling setSideBarVisible(true) when sideBarDef.hideButtons is set to true and no tool panel is open will not display anything.
The Popup Parent must be set to an element that contains both the tool panel parent and the grid to ensure all popups (e.g., Columns Tool Panel context menus) are fully visible.
Configuration Shortcuts Copy Link
The boolean and string configurations are shortcuts for more detailed configurations. When you use a shortcut the grid replaces it with the equivalent long form of the configuration by building the equivalent SideBarDef.
The following code snippets show an example of the boolean shortcut and the equivalent SideBarDef long form.
// shortcut
const sideBar = true;
<AgGridReact sideBar={sideBar} />// equivalent detailed long form
const sideBar = useMemo(() => {
return {
toolPanels: [
{
id: 'columns',
labelDefault: 'Columns',
labelKey: 'columns',
iconKey: 'columns',
toolPanel: 'agColumnsToolPanel',
},
{
id: 'filters',
labelDefault: 'Filters',
labelKey: 'filters',
iconKey: 'filter',
toolPanel: 'agFiltersToolPanel',
}
],
defaultToolPanel: 'columns',
};
}, []);
<AgGridReact sideBar={sideBar} />The following code snippets show an example of the string shortcut and the equivalent SideBarDef long form.
// shortcut
const sideBar = 'filters';
<AgGridReact sideBar={sideBar} />// equivalent detailed long form
const sideBar = useMemo(() => {
return {
toolPanels: [
{
id: 'filters',
labelDefault: 'Filters',
labelKey: 'filters',
iconKey: 'filter',
toolPanel: 'agFiltersToolPanel',
}
],
defaultToolPanel: 'filters',
};
}, []);
<AgGridReact sideBar={sideBar} />You can also use shortcuts inside the sideBar.toolPanels array for specifying the Columns and Filters items.
// shortcut
const sideBar = useMemo(() => {
return {
toolPanels: ['columns', 'filters']
};
}, []);
<AgGridReact sideBar={sideBar} />// equivalent detailed long form
const sideBar = useMemo(() => {
return {
toolPanels: [
{
id: 'columns',
labelDefault: 'Columns',
labelKey: 'columns',
iconKey: 'columns',
toolPanel: 'agColumnsToolPanel',
},
{
id: 'filters',
labelDefault: 'Filters',
labelKey: 'filters',
iconKey: 'filter',
toolPanel: 'agFiltersToolPanel',
}
]
};
}, []);
<AgGridReact sideBar={sideBar} /> Side Bar Customisation Copy Link
If you are using the long form (providing a SideBarDef object) then it is possible to customise. The example below changes the filter label and icon.
"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 {
AutoGroupColumnDef,
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
NumberFilterModule,
SideBarDef,
TextFilterModule,
enableDevValidations,
} from "ag-grid-community";
import {
ColumnsToolPanelModule,
FiltersToolPanelModule,
PivotModule,
SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [
NumberFilterModule,
ClientSideRowModelModule,
ColumnsToolPanelModule,
FiltersToolPanelModule,
SetFilterModule,
PivotModule,
TextFilterModule,
];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "athlete", filter: "agTextColumnFilter", minWidth: 200 },
{ field: "age" },
{ field: "country", minWidth: 180 },
{ field: "year" },
{ field: "date", minWidth: 150 },
{ field: "gold" },
{ field: "silver" },
{ field: "bronze" },
{ field: "total" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
// allow every column to be aggregated
enableValue: true,
// allow every column to be grouped
enableRowGroup: true,
// allow every column to be pivoted
enablePivot: true,
filter: true,
};
}, []);
const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
return {
minWidth: 200,
};
}, []);
const sideBar = useMemo<
SideBarDef | string | string[] | boolean | null
>(() => {
return {
toolPanels: [
"columns",
{
id: "filters",
labelKey: "filters",
labelDefault: "Filters",
iconKey: "menu",
toolPanel: "agFiltersToolPanel",
},
{
id: "filters 2",
labelKey: "filters",
labelDefault: "Filters XXXXXXXX",
iconKey: "filter",
toolPanel: "agFiltersToolPanel",
},
],
defaultToolPanel: "filters",
};
}, []);
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}
autoGroupColumnDef={autoGroupColumnDef}
sideBar={sideBar}
/>
</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(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
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;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; Tool Panel Parent Copy Link
By default, Tool Panels are rendered inside the Side Bar. If you want to render Tool Panels in a different location, you can set the parent property in the ToolPanelDef. This is useful if you want to render Tool Panel in a different part of your application, such as a popup window or a separate section of your page.
To ensure correct panel sizing, AG Grid adds a CSS class to the parent element. If your component also sets the parent class it may overwrite this, so include the ag-tool-panel-external class when setting the parent class:
<div ref={toolPanelParent}
className="your-app-class ag-tool-panel-external"></div>The Popup Parent must also be set to an element that contains both the Tool Panel parent and the grid.
You can also provide a parent for the tool panel in the call to openToolPanel method:
Opens a particular tool panel. Provide the ID of the tool panel to open.
Optionally, provide a parent element to attach the tool panel to. |
"use client";
import React, {
StrictMode,
useCallback,
useMemo,
useRef,
useState,
} from "react";
import { createRoot } from "react-dom/client";
import {
ClientSideRowModelModule,
ColumnsToolPanelModule,
NewFiltersToolPanelModule,
NumberFilterModule,
PivotModule,
SetFilterModule,
TextFilterModule,
enableDevValidations,
} from "ag-grid-enterprise";
import { AgGridProvider, AgGridReact } from "ag-grid-react";
import "./styles.css";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [
NumberFilterModule,
ClientSideRowModelModule,
ColumnsToolPanelModule,
NewFiltersToolPanelModule,
SetFilterModule,
PivotModule,
TextFilterModule,
];
const GridExample = () => {
const gridRef = useRef(null);
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const popupRef = useRef<HTMLElement>(null);
const popupContentRef = useRef<HTMLElement>(null);
const drawerRef = useRef<HTMLElement>(null);
const drawerContentRef = useRef<HTMLElement>(null);
const [popupParent, setPopupParent] = useState<HTMLElement | null>(
document.body,
);
const [columnDefs, setColumnDefs] = useState([
{ field: "athlete", filter: "agTextColumnFilter", minWidth: 200 },
{ field: "country", minWidth: 180 },
{ field: "date", minWidth: 150 },
{ field: "gold", minWidth: 150 },
{ field: "silver", minWidth: 150 },
]);
const defaultColDef = useMemo(
() => ({ flex: 1, minWidth: 100, filter: true }),
[],
);
const autoGroupColumnDef = useMemo(() => ({ minWidth: 200 }), []);
const { data, loading } = useFetchJson(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
const columnsToolPanel = useMemo(() => {
return {
id: "columns",
labelDefault: "Popup",
labelKey: "columns",
iconKey: "columnsToolPanel",
toolPanel: "agColumnsToolPanel",
toolPanelParams: {
suppressRowGroups: true,
suppressValues: true,
suppressPivotMode: true,
},
parent: popupContentRef.current,
};
}, [popupRef.current, popupContentRef.current]);
const filtersToolPanel = useMemo(
() => ({
id: "filters",
labelDefault: "Drawer",
labelKey: "filters",
iconKey: "filter",
toolPanel: "agNewFiltersToolPanel",
}),
[],
);
const sideBar = useMemo(
() => ({
toolPanels: [columnsToolPanel, filtersToolPanel],
hideButtons: true,
hiddenByDefault: true,
}),
[columnsToolPanel, filtersToolPanel],
);
const closePopup = useCallback(() => {
const drawer = popupRef.current;
drawer.classList.toggle("active", false);
gridRef.current.api.closeToolPanel();
}, [popupRef.current]);
const closeDrawer = useCallback(() => {
const drawer = drawerRef.current;
drawer.classList.toggle("active", false);
gridRef.current.api.closeToolPanel();
}, [drawerRef.current]);
const openPopup = useCallback(() => {
closeDrawer();
const popup = popupRef.current;
popup.classList.toggle("active", true);
gridRef.current.api.openToolPanel(columnsToolPanel.id);
}, [popupRef.current, closeDrawer, columnsToolPanel]);
const openDrawer = useCallback(() => {
closePopup();
const drawer = drawerRef.current;
drawer.classList.toggle("active", true);
gridRef.current.api.openToolPanel(
filtersToolPanel.id,
drawerContentRef.current,
);
}, [drawerRef, closePopup, filtersToolPanel]);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div id="wrapper" className="example-wrapper">
<div className="example-header">
<button onClick={openPopup}>Open Columns Tool Panel</button>
<button onClick={openDrawer}>Open Filters Tool Panel</button>
</div>
<div style={gridStyle}>
<AgGridReact
enableFilterHandlers
ref={gridRef}
rowData={data}
loading={loading}
popupParent={popupParent}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
autoGroupColumnDef={autoGroupColumnDef}
sideBar={sideBar}
/>
</div>
</div>
<div id="popup" ref={popupRef}>
<div className="inner">
<div>
<button onClick={closePopup}>Close</button>
</div>
<div className="content" ref={popupContentRef}></div>
</div>
</div>
<div id="drawer" ref={drawerRef}>
<div className="inner">
<div>
<button onClick={closeDrawer}>Close</button>
</div>
<div className="content" ref={drawerContentRef}></div>
</div>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root"));
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
.example-wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
#myGrid {
flex: 1 1 0;
width: 100%;
}
.example-header {
margin-bottom: 10px;
}
#drawer.active,
#popup.active {
display: flex;
}
/* Base styles for the container */
#popup {
display: none; /* Hidden by default */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
& .inner {
min-width: 300px;
}
& .content {
min-height: 200px;
}
}
#popup .inner {
border: 1px solid;
padding: 20px;
border-radius: 10px;
-webkit-font-smoothing: antialiased;
background-color: var(--example-background-color, white);
color: var(--example-text-color, black);
color-scheme: var(--example-color-scheme);
font-family: var(--example-font-family, Arial), sans-serif;
flex-direction: column;
}
/* Base styles for the container */
#drawer {
& .inner {
min-width: 300px;
}
& .content {
min-height: 200px;
}
position: fixed;
z-index: 2;
top: 54px;
bottom: 0;
width: 300px;
display: flex;
transform: translateX(-344px);
transition: transform 0.3s ease-in-out;
}
#drawer .content {
height: calc(100% - 90px);
}
#drawer .inner {
border: 1px solid;
padding: 20px;
border-radius: 10px;
-webkit-font-smoothing: antialiased;
background-color: var(--example-background-color, white);
color: var(--example-text-color, black);
color-scheme: var(--example-color-scheme);
font-family: var(--example-font-family, Arial), sans-serif;
flex-direction: column;
}
#drawer.active {
transform: translateX(0);
}
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(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
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;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; Providing Parameters to Tool Panels Copy Link
Parameters are passed to Tool Panels via the toolPanelParams object. For example, the following code snippet sets suppressRowGroups: true and suppressValues: true for the Columns Tool Panel.
const sideBar = useMemo(() => {
return {
toolPanels: [
{
id: 'columns',
labelDefault: 'Columns',
labelKey: 'columns',
iconKey: 'columns',
toolPanel: 'agColumnsToolPanel',
toolPanelParams: {
suppressRowGroups: true,
suppressValues: true,
}
}
]
};
}, []);
<AgGridReact sideBar={sideBar} />See the Columns Tool Panel documentation for the full list of possible parameters to this Tool Panel.
Animation Copy Link
By default, sidebar panels open and close instantly. You can enable a smooth slide animation using the Theming API parameter sideBarPanelAnimationDuration. Set it to a value in seconds:
const myTheme = themeQuartz.withParams({
sideBarPanelAnimationDuration: 0.3,
});The animation is automatically disabled for users who have requested reduced motion in their OS accessibility settings.
"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,
NumberFilterModule,
SideBarDef,
TextFilterModule,
Theme,
enableDevValidations,
themeQuartz,
} from "ag-grid-community";
import {
ColumnsToolPanelModule,
NewFiltersToolPanelModule,
PivotModule,
SideBarModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [
ClientSideRowModelModule,
ColumnsToolPanelModule,
NewFiltersToolPanelModule,
TextFilterModule,
NumberFilterModule,
SideBarModule,
PivotModule,
];
const myTheme = themeQuartz.withParams({
sideBarPanelAnimationDuration: 0.3,
});
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" },
{ field: "year" },
]);
const theme = useMemo<Theme | "legacy">(() => {
return myTheme;
}, []);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
filter: true,
sortable: true,
resizable: true,
};
}, []);
const sideBar = useMemo<
SideBarDef | string | string[] | boolean | null
>(() => {
return ["columns", "filters-new"];
}, []);
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}
theme={theme}
defaultColDef={defaultColDef}
enableFilterHandlers={true}
sideBar={sideBar}
/>
</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(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
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;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; Side Bar API Copy Link
The Side Bar state can be saved and restored as part of Grid State.
The list below details all the API methods relevant to the Tool Panel.
Returns the current side bar configuration. If a shortcut was used, returns the detailed long form. |
Show/hide the entire side bar, including any visible panel and the tab buttons. |
Returns true if the side bar is visible. |
Sets the side bar position relative to the grid. Possible values are 'left' or 'right'. |
Opens a particular tool panel. Provide the ID of the tool panel to open.
Optionally, provide a parent element to attach the tool panel to. |
Closes the currently open tool panel (if any). |
Returns the ID of the currently shown tool panel if any, otherwise null. |
Returns true if the tool panel is showing, otherwise false. |
Force refreshes all tool panels by calling their refresh method. |
Gets the tool panel instance corresponding to the supplied id. |
The example below demonstrates different usages of the Tool Panel API methods. The following can be noted:
- Initially the Side Bar is not visible as
sideBar.hiddenByDefault=true. - Visibility Buttons: These toggle visibility of the Tool Panel. Note that when you make
visible=false, the entire Tool Panel is hidden including the tabs. Make sure the Tool Panel is left visible before testing the other API features so you can see the impact. - Open / Close Buttons: These open and close different Tool Panel items.
- Reset Buttons: These reset the Tool Panel to a new configuration. Notice that shortcuts are provided as configuration however
getSideBar()returns back the long form. - Position Buttons: These change the position of the Side Bar relative to the grid.
- The
get*buttons log data to the developer console.
("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,
NumberFilterModule,
SideBarDef,
TextFilterModule,
ToolPanelSizeChangedEvent,
ToolPanelVisibleChangedEvent,
enableDevValidations,
} from "ag-grid-community";
import {
ColumnsToolPanelModule,
FiltersToolPanelModule,
PivotModule,
SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [
NumberFilterModule,
ClientSideRowModelModule,
ColumnsToolPanelModule,
FiltersToolPanelModule,
SetFilterModule,
PivotModule,
TextFilterModule,
];
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", filter: "agTextColumnFilter", minWidth: 200 },
{ field: "age" },
{ field: "country", minWidth: 200 },
{ field: "year" },
{ field: "date", minWidth: 160 },
{ field: "gold" },
{ field: "silver" },
{ field: "bronze" },
{ field: "total" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
// allow every column to be aggregated
enableValue: true,
// allow every column to be grouped
enableRowGroup: true,
// allow every column to be pivoted
enablePivot: true,
filter: true,
};
}, []);
const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
return {
minWidth: 200,
};
}, []);
const sideBar = useMemo<
SideBarDef | string | string[] | boolean | null
>(() => {
return {
toolPanels: [
{
id: "columns",
labelDefault: "Columns",
labelKey: "columns",
iconKey: "columns",
toolPanel: "agColumnsToolPanel",
},
{
id: "filters",
labelDefault: "Filters",
labelKey: "filters",
iconKey: "filter",
toolPanel: "agFiltersToolPanel",
},
],
defaultToolPanel: "filters",
hiddenByDefault: true,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
const onToolPanelVisibleChanged = useCallback(
(event: ToolPanelVisibleChangedEvent) => {
console.log("toolPanelVisibleChanged", event);
},
[],
);
const onToolPanelSizeChanged = useCallback(
(event: ToolPanelSizeChangedEvent) => {
console.log("toolPanelSizeChanged", event);
},
[],
);
const setSideBarVisible = useCallback((value: boolean) => {
gridRef.current!.api.setSideBarVisible(value);
}, []);
const isSideBarVisible = useCallback(() => {
console.log(gridRef.current!.api.isSideBarVisible());
}, []);
const openToolPanel = useCallback((key: string) => {
gridRef.current!.api.openToolPanel(key);
}, []);
const closeToolPanel = useCallback(() => {
gridRef.current!.api.closeToolPanel();
}, []);
const getOpenedToolPanel = useCallback(() => {
console.log(gridRef.current!.api.getOpenedToolPanel());
}, []);
const setSideBar = useCallback(
(def: SideBarDef | string | string[] | boolean) => {
gridRef.current!.api.setGridOption("sideBar", def);
},
[],
);
const getSideBar = useCallback(() => {
const sideBar = gridRef.current!.api.getSideBar();
console.log(JSON.stringify(sideBar));
console.log(sideBar);
}, []);
const setSideBarPosition = useCallback((position: "left" | "right") => {
gridRef.current!.api.setSideBarPosition(position);
}, []);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div className="parent-div">
<div className="api-panel">
<div className="api-column">
Visibility
<button onClick={() => setSideBarVisible(true)}>
setSideBarVisible(true)
</button>
<button onClick={() => setSideBarVisible(false)}>
setSideBarVisible(false)
</button>
<button onClick={isSideBarVisible}>isSideBarVisible()</button>
</div>
<div className="api-column">
Open & Close
<button onClick={() => openToolPanel("columns")}>
openToolPanel('columns')
</button>
<button onClick={() => openToolPanel("filters")}>
openToolPanel('filters')
</button>
<button onClick={closeToolPanel}>closeToolPanel()</button>
<button onClick={getOpenedToolPanel}>getOpenedToolPanel()</button>
</div>
<div className="api-column">
Reset
<button onClick={() => setSideBar(["filters", "columns"])}>
setSideBar(['filters','columns'])
</button>
<button onClick={() => setSideBar("columns")}>
setSideBar('columns')
</button>
<button onClick={getSideBar}>getSideBar()</button>
</div>
<div className="api-column">
Position
<button onClick={() => setSideBarPosition("left")}>
setSideBarPosition('left')
</button>
<button onClick={() => setSideBarPosition("right")}>
setSideBarPosition('right')
</button>
</div>
</div>
<div style={gridStyle} className="grid-div">
<AgGridReact<IOlympicData>
ref={gridRef}
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
autoGroupColumnDef={autoGroupColumnDef}
sideBar={sideBar}
onToolPanelVisibleChanged={onToolPanelVisibleChanged}
onToolPanelSizeChanged={onToolPanelSizeChanged}
/>
</div>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
.api-panel {
display: flex;
flex-direction: row;
flex-wrap: wrap;
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 13px;
}
.api-column {
padding: 0px 5px 5px;
text-align: center;
width: 215px;
max-height: 200px;
}
.api-column button {
width: 100%;
}
.api-column button:first-child {
margin-top: 5px;
}
.api-panel button {
margin: 2px;
}
.grid-div {
height: 100%;
}
.parent-div {
height: 100%;
display: grid;
grid-template-rows: auto 1fr;
}
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(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
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;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
};