AG Grid React Component wrapper for integrating the high-performance data grid into React applications
—
Specialized React hooks for integrating custom component callbacks with the AG Grid system, providing seamless communication between React components and the grid.
Hook for integrating custom cell editor components with the grid's editing system.
/**
* Hook to allow custom cell editor component callbacks to be provided to the grid
* @param callbacks - Cell editor callback implementations
*/
function useGridCellEditor(callbacks: CustomCellEditorCallbacks): void;
/**
* Callbacks for custom cell editor components
*/
interface CustomCellEditorCallbacks extends BaseCellEditor {}Usage Example:
import React, { useState, useRef, useImperativeHandle, forwardRef } from 'react';
import { useGridCellEditor, CustomCellEditorProps } from 'ag-grid-react';
const NumericCellEditor = forwardRef<any, CustomCellEditorProps<any, number>>((props, ref) => {
const [value, setValue] = useState<number>(props.initialValue || 0);
const inputRef = useRef<HTMLInputElement>(null);
// Use the hook to provide callbacks to the grid
useGridCellEditor({
getValue: () => value,
isPopup: () => false,
isCancelBeforeStart: () => {
// Cancel editing if initial value is invalid
return isNaN(props.initialValue as number);
},
isCancelAfterEnd: () => {
// Cancel if final value is invalid
return isNaN(value);
},
focusIn: () => {
// Custom focus behavior
if (inputRef.current) {
inputRef.current.focus();
inputRef.current.select();
}
},
focusOut: () => {
// Custom blur behavior
console.log('Editor lost focus');
}
});
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = parseFloat(e.target.value) || 0;
setValue(newValue);
props.onValueChange(newValue);
};
return (
<input
ref={inputRef}
type="number"
value={value}
onChange={handleChange}
style={{ width: '100%', height: '100%' }}
/>
);
});Hook for integrating custom date picker components with date filters.
/**
* Hook to allow custom date component callbacks to be provided to the grid
* @param callbacks - Date callback implementations
*/
function useGridDate(callbacks: CustomDateCallbacks): void;
/**
* Callbacks for custom date components
*/
interface CustomDateCallbacks extends BaseDate {}Usage Example:
import React, { useState, useEffect } from 'react';
import { useGridDate, CustomDateProps } from 'ag-grid-react';
const CustomDatePicker: React.FC<CustomDateProps> = (props) => {
const [selectedDate, setSelectedDate] = useState<Date | null>(props.date);
// Use the hook to provide callbacks to the grid
useGridDate({
getDate: () => selectedDate,
setDate: (date: Date | null) => {
setSelectedDate(date);
},
refresh: () => {
// Refresh the component if needed
setSelectedDate(props.date);
}
});
const handleDateChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const newDate = event.target.value ? new Date(event.target.value) : null;
setSelectedDate(newDate);
props.onDateChange(newDate);
};
const dateString = selectedDate ? selectedDate.toISOString().split('T')[0] : '';
return (
<div style={{ padding: '8px' }}>
<input
type="date"
value={dateString}
onChange={handleDateChange}
style={{ width: '100%' }}
/>
<button
onClick={() => {
setSelectedDate(null);
props.onDateChange(null);
}}
style={{ marginTop: '4px', width: '100%' }}
>
Clear
</button>
</div>
);
};Hook for integrating custom filter components with the grid's filtering system.
/**
* Hook to allow custom filter component callbacks to be provided to the grid
* @param callbacks - Filter callback implementations
*/
function useGridFilter(callbacks: CustomFilterCallbacks): void;
/**
* Callbacks for custom filter components
*/
interface CustomFilterCallbacks extends BaseFilter {}Usage Example:
import React, { useState, useEffect } from 'react';
import { useGridFilter, CustomFilterProps } from 'ag-grid-react';
interface RangeFilterModel {
filterType: 'range';
min: number | null;
max: number | null;
}
const RangeFilter: React.FC<CustomFilterProps<any, any, RangeFilterModel>> = (props) => {
const [min, setMin] = useState<number | null>(props.model?.min || null);
const [max, setMax] = useState<number | null>(props.model?.max || null);
// Use the hook to provide callbacks to the grid
useGridFilter({
doesFilterPass: (params) => {
const value = props.valueGetter(params);
const numValue = parseFloat(value);
if (isNaN(numValue)) return false;
if (min !== null && numValue < min) return false;
if (max !== null && numValue > max) return false;
return true;
},
isFilterActive: () => min !== null || max !== null,
getModel: () => {
if (min === null && max === null) return null;
return { filterType: 'range', min, max };
},
setModel: (model: RangeFilterModel | null) => {
if (model) {
setMin(model.min);
setMax(model.max);
} else {
setMin(null);
setMax(null);
}
},
refresh: () => {
// Refresh the component if needed
return true;
}
});
const handleMinChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value ? parseFloat(e.target.value) : null;
setMin(value);
updateModel(value, max);
};
const handleMaxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value ? parseFloat(e.target.value) : null;
setMax(value);
updateModel(min, value);
};
const updateModel = (newMin: number | null, newMax: number | null) => {
if (newMin === null && newMax === null) {
props.onModelChange(null);
} else {
props.onModelChange({ filterType: 'range', min: newMin, max: newMax });
}
};
return (
<div style={{ padding: '8px' }}>
<div style={{ marginBottom: '8px' }}>
<label>Min:</label>
<input
type="number"
value={min || ''}
onChange={handleMinChange}
placeholder="Min value"
style={{ width: '100%' }}
/>
</div>
<div>
<label>Max:</label>
<input
type="number"
value={max || ''}
onChange={handleMaxChange}
placeholder="Max value"
style={{ width: '100%' }}
/>
</div>
</div>
);
};Hook for integrating custom filter display components when using enableFilterHandlers = true.
/**
* Hook to allow custom filter component callbacks when using enableFilterHandlers = true
* @param callbacks - Filter display callback implementations
*/
function useGridFilterDisplay(callbacks: CustomFilterDisplayCallbacks): void;
/**
* Callbacks for custom filter components when using enableFilterHandlers = true
*/
interface CustomFilterDisplayCallbacks extends SharedFilterUi {}Hook for integrating custom floating filter components with the grid's filtering system.
/**
* Hook to allow custom floating filter component callbacks to be provided to the grid
* @param callbacks - Floating filter callback implementations
*/
function useGridFloatingFilter(callbacks: CustomFloatingFilterCallbacks): void;
/**
* Callbacks for custom floating filter components
*/
interface CustomFloatingFilterCallbacks extends BaseFloatingFilter {}Usage Example:
import React, { useState, useEffect } from 'react';
import { useGridFloatingFilter, CustomFloatingFilterProps } from 'ag-grid-react';
const QuickSearchFloatingFilter: React.FC<CustomFloatingFilterProps> = (props) => {
const [filterText, setFilterText] = useState('');
// Use the hook to provide callbacks to the grid
useGridFloatingFilter({
onParentModelChanged: (parentModel) => {
// Update floating filter when parent filter changes
setFilterText(parentModel?.filter || '');
},
refresh: () => {
// Refresh the floating filter
return true;
}
});
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setFilterText(value);
// Update the parent filter
if (value) {
props.parentFilterInstance(instance => {
instance.setModel({ filter: value, type: 'contains' });
props.api.onFilterChanged();
});
} else {
props.parentFilterInstance(instance => {
instance.setModel(null);
props.api.onFilterChanged();
});
}
};
return (
<input
type="text"
value={filterText}
onChange={handleInputChange}
placeholder="Quick search..."
style={{
width: '100%',
height: '100%',
border: 'none',
padding: '4px 8px'
}}
/>
);
};Hook for integrating custom menu item components with context and column menus.
/**
* Hook to allow custom menu item component callbacks to be provided to the grid
* @param callbacks - Menu item callback implementations
*/
function useGridMenuItem(callbacks: CustomMenuItemCallbacks): void;
/**
* Callbacks for custom menu item components
*/
interface CustomMenuItemCallbacks extends BaseMenuItem {}Usage Example:
import React, { useState } from 'react';
import { useGridMenuItem, CustomMenuItemProps } from 'ag-grid-react';
const InteractiveMenuItem: React.FC<CustomMenuItemProps> = (props) => {
const [isProcessing, setIsProcessing] = useState(false);
// Use the hook to provide callbacks to the grid
useGridMenuItem({
configureDefaults: () => {
// Configure default behavior
return {
name: props.name,
disabled: props.disabled,
tooltip: props.tooltip
};
}
});
const handleClick = async () => {
if (props.action) {
setIsProcessing(true);
try {
await props.action();
} catch (error) {
console.error('Menu action failed:', error);
} finally {
setIsProcessing(false);
}
}
};
return (
<div
onClick={handleClick}
style={{
padding: '8px 16px',
cursor: props.disabled || isProcessing ? 'not-allowed' : 'pointer',
opacity: props.disabled || isProcessing ? 0.5 : 1,
backgroundColor: props.active ? '#f0f0f0' : 'transparent',
display: 'flex',
alignItems: 'center',
gap: '8px'
}}
>
{isProcessing ? (
<span>⏳</span>
) : (
props.icon && <span>{props.icon}</span>
)}
<span>{props.name}</span>
</div>
);
};Example showing how to combine multiple hooks in a complex custom component:
import React, { useState, useEffect, useRef } from 'react';
import {
useGridCellEditor,
useGridFilter,
CustomCellEditorProps,
CustomFilterProps
} from 'ag-grid-react';
// Multi-purpose component that can act as both editor and filter
const MultiPurposeComponent: React.FC<CustomCellEditorProps & CustomFilterProps> = (props) => {
const [value, setValue] = useState(props.initialValue || props.model?.value || '');
const inputRef = useRef<HTMLInputElement>(null);
const isEditor = 'onValueChange' in props;
const isFilter = 'onModelChange' in props;
// Editor integration
if (isEditor) {
useGridCellEditor({
getValue: () => value,
focusIn: () => inputRef.current?.focus(),
isCancelBeforeStart: () => false,
isCancelAfterEnd: () => false
});
}
// Filter integration
if (isFilter) {
useGridFilter({
doesFilterPass: (params) => {
const cellValue = props.valueGetter(params);
return String(cellValue).toLowerCase().includes(String(value).toLowerCase());
},
isFilterActive: () => !!value,
getModel: () => value ? { value } : null,
setModel: (model) => setValue(model?.value || '')
});
}
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = e.target.value;
setValue(newValue);
if (isEditor && props.onValueChange) {
props.onValueChange(newValue);
}
if (isFilter && props.onModelChange) {
props.onModelChange(newValue ? { value: newValue } : null);
}
};
return (
<input
ref={inputRef}
type="text"
value={value}
onChange={handleChange}
style={{ width: '100%', height: '100%' }}
placeholder={isEditor ? 'Enter value...' : 'Filter...'}
/>
);
};Install with Tessl CLI
npx tessl i tessl/npm-ag-grid-react