feat(ag-grid): Server Side Filtering for Column Level Filters (#35683)

This commit is contained in:
amaannawab923
2026-01-12 19:25:07 +05:30
committed by GitHub
parent 459b4cb23d
commit 4f444ae1d2
20 changed files with 4142 additions and 95 deletions

View File

@@ -55,7 +55,9 @@ import Pagination from './components/Pagination';
import SearchSelectDropdown from './components/SearchSelectDropdown';
import { SearchOption, SortByItem } from '../types';
import getInitialSortState, { shouldSort } from '../utils/getInitialSortState';
import getInitialFilterModel from '../utils/getInitialFilterModel';
import { PAGE_SIZE_OPTIONS } from '../consts';
import { getCompleteFilterState } from '../utils/filterStateManager';
export interface AgGridState extends Partial<GridState> {
timestamp?: number;
@@ -100,6 +102,8 @@ export interface AgGridTableProps {
showTotals: boolean;
width: number;
onColumnStateChange?: (state: AgGridChartStateWithMetadata) => void;
onFilterChanged?: (filterModel: Record<string, any>) => void;
metricColumns?: string[];
gridRef?: RefObject<AgGridReact>;
chartState?: AgGridChartState;
}
@@ -137,6 +141,8 @@ const AgGridDataTable: FunctionComponent<AgGridTableProps> = memo(
showTotals,
width,
onColumnStateChange,
onFilterChanged,
metricColumns = [],
chartState,
}) => {
const gridRef = useRef<AgGridReact>(null);
@@ -144,14 +150,27 @@ const AgGridDataTable: FunctionComponent<AgGridTableProps> = memo(
const rowData = useMemo(() => data, [data]);
const containerRef = useRef<HTMLDivElement>(null);
const lastCapturedStateRef = useRef<string | null>(null);
const filterOperationVersionRef = useRef(0);
const searchId = `search-${id}`;
const initialFilterModel = getInitialFilterModel(
chartState,
serverPaginationData,
serverPagination,
);
const gridInitialState: GridState = {
...(serverPagination && {
sort: {
sortModel: getInitialSortState(serverPaginationData?.sortBy || []),
},
}),
...(initialFilterModel && {
filter: {
filterModel: initialFilterModel,
},
}),
};
const defaultColDef = useMemo<ColDef>(
@@ -332,6 +351,56 @@ const AgGridDataTable: FunctionComponent<AgGridTableProps> = memo(
[onColumnStateChange],
);
const handleFilterChanged = useCallback(async () => {
filterOperationVersionRef.current += 1;
const currentVersion = filterOperationVersionRef.current;
const completeFilterState = await getCompleteFilterState(
gridRef,
metricColumns,
);
// Skip stale operations from rapid filter changes
if (currentVersion !== filterOperationVersionRef.current) {
return;
}
// Reject invalid filter states (e.g., text filter on numeric column)
if (completeFilterState.originalFilterModel) {
const filterModel = completeFilterState.originalFilterModel;
const hasInvalidFilterType = Object.entries(filterModel).some(
([colId, filter]: [string, any]) => {
if (
filter?.filterType === 'text' &&
metricColumns?.includes(colId)
) {
return true;
}
return false;
},
);
if (hasInvalidFilterType) {
return;
}
}
if (
!isEqual(
serverPaginationData?.agGridFilterModel,
completeFilterState.originalFilterModel,
)
) {
if (onFilterChanged) {
onFilterChanged(completeFilterState);
}
}
}, [
onFilterChanged,
metricColumns,
serverPaginationData?.agGridFilterModel,
]);
useEffect(() => {
if (
hasServerPageLengthChanged &&
@@ -356,19 +425,14 @@ const AgGridDataTable: FunctionComponent<AgGridTableProps> = memo(
// This will make columns fill the grid width
params.api.sizeColumnsToFit();
// Restore saved AG Grid state from permalink if available
if (chartState && params.api) {
// Restore saved column state from permalink if available
// Note: filterModel is now handled via gridInitialState for better performance
if (chartState?.columnState && params.api) {
try {
if (chartState.columnState) {
params.api.applyColumnState?.({
state: chartState.columnState as ColumnState[],
applyOrder: true,
});
}
if (chartState.filterModel) {
params.api.setFilterModel?.(chartState.filterModel);
}
params.api.applyColumnState?.({
state: chartState.columnState as ColumnState[],
applyOrder: true,
});
} catch {
// Silently fail if state restoration fails
}
@@ -429,6 +493,7 @@ const AgGridDataTable: FunctionComponent<AgGridTableProps> = memo(
rowSelection="multiple"
animateRows
onCellClicked={handleCrossFilter}
onFilterChanged={handleFilterChanged}
onStateUpdated={handleGridStateChange}
initialState={gridInitialState}
maintainColumnOrder
@@ -520,6 +585,9 @@ const AgGridDataTable: FunctionComponent<AgGridTableProps> = memo(
serverPaginationData?.sortBy || [],
),
isActiveFilterValue,
lastFilteredColumn: serverPaginationData?.lastFilteredColumn,
lastFilteredInputPosition:
serverPaginationData?.lastFilteredInputPosition,
}}
/>
{serverPagination && (