@@ -39,6 +39,7 @@ import {
3939 CellClickedEvent ,
4040 IMenuActionParams ,
4141} from '@superset-ui/core/components/ThemedAgGridReact' ;
42+ import type { FilterChangedEvent } from 'ag-grid-community' ;
4243import { type FunctionComponent } from 'react' ;
4344import { JsonObject , DataRecordValue , DataRecord , t } from '@superset-ui/core' ;
4445import { SearchOutlined } from '@ant-design/icons' ;
@@ -48,6 +49,11 @@ import SearchSelectDropdown from './components/SearchSelectDropdown';
4849import { SearchOption , SortByItem } from '../types' ;
4950import getInitialSortState , { shouldSort } from '../utils/getInitialSortState' ;
5051import { PAGE_SIZE_OPTIONS } from '../consts' ;
52+ import {
53+ convertAgGridFiltersToSQL ,
54+ logFilterConversion ,
55+ type AgGridFilterModel ,
56+ } from '../utils/agGridFilterConverter' ;
5157
5258export interface AgGridTableProps {
5359 gridTheme ?: string ;
@@ -70,6 +76,7 @@ export interface AgGridTableProps {
7076 onSearchColChange : ( searchCol : string ) => void ;
7177 onSearchChange : ( searchText : string ) => void ;
7278 onSortChange : ( sortBy : SortByItem [ ] ) => void ;
79+ onAgGridColumnFiltersChange ?: ( filterModel : AgGridFilterModel ) => void ;
7380 id : number ;
7481 percentMetrics : string [ ] ;
7582 serverPageLength : number ;
@@ -104,6 +111,7 @@ const AgGridDataTable: FunctionComponent<AgGridTableProps> = memo(
104111 onSearchColChange,
105112 onSearchChange,
106113 onSortChange,
114+ onAgGridColumnFiltersChange,
107115 id,
108116 percentMetrics,
109117 serverPageLength,
@@ -153,6 +161,11 @@ const AgGridDataTable: FunctionComponent<AgGridTableProps> = memo(
153161 serverPaginationData ?. searchText || '' ,
154162 ) ;
155163
164+ // State to store column-level filters - initialize from ownState if available
165+ const [ columnFilters , setColumnFilters ] = useState < any > (
166+ serverPaginationData ?. agGridFilterModel || { } ,
167+ ) ;
168+
156169 const debouncedSearch = useMemo (
157170 ( ) =>
158171 debounce ( ( value : string ) => {
@@ -254,11 +267,75 @@ const AgGridDataTable: FunctionComponent<AgGridTableProps> = memo(
254267 }
255268 } , [ width ] ) ;
256269
270+ // Restore AG Grid filter state from ownState (similar to search box pattern)
271+ useEffect ( ( ) => {
272+ if ( gridRef . current ?. api && serverPagination ) {
273+ const storedFilterModel = serverPaginationData ?. agGridFilterModel ;
274+
275+ if ( storedFilterModel && Object . keys ( storedFilterModel ) . length > 0 ) {
276+ // Only restore if the current filter model is different
277+ const currentFilterModel = gridRef . current . api . getFilterModel ( ) ;
278+
279+ if ( ! isEqual ( currentFilterModel , storedFilterModel ) ) {
280+ console . log ( 'Restoring AG Grid filters from ownState:' , storedFilterModel ) ;
281+ gridRef . current . api . setFilterModel ( storedFilterModel ) ;
282+ }
283+ } else if ( Object . keys ( columnFilters ) . length > 0 ) {
284+ // Clear filters if ownState has no filters but local state does
285+ console . log ( 'Clearing AG Grid filters (ownState is empty)' ) ;
286+ gridRef . current . api . setFilterModel ( null ) ;
287+ setColumnFilters ( { } ) ;
288+ }
289+ }
290+ } , [ serverPaginationData ?. agGridFilterModel , serverPagination ] ) ;
291+
257292 const onGridReady = ( params : GridReadyEvent ) => {
258293 // This will make columns fill the grid width
259294 params . api . sizeColumnsToFit ( ) ;
295+
296+ // Restore filter state on grid ready if server pagination is enabled
297+ if ( serverPagination && serverPaginationData ?. agGridFilterModel ) {
298+ const storedFilterModel = serverPaginationData . agGridFilterModel ;
299+ if ( Object . keys ( storedFilterModel ) . length > 0 ) {
300+ console . log ( 'Restoring AG Grid filters on grid ready:' , storedFilterModel ) ;
301+ params . api . setFilterModel ( storedFilterModel ) ;
302+ }
303+ }
260304 } ;
261305
306+ // Handler for column filter changes
307+ const onFilterChanged = useCallback ( ( event : FilterChangedEvent ) => {
308+ const filterModel = event . api . getFilterModel ( ) ;
309+ console . log ( 'Column Filters Changed:' , filterModel ) ;
310+
311+ // Only trigger API call if filters actually changed (deep comparison)
312+ // This prevents infinite loops when restoring filters from ownState
313+ if ( isEqual ( filterModel , serverPaginationData ?. agGridFilterModel ) ) {
314+ console . log ( 'Filter model unchanged - skipping API call' ) ;
315+ return ;
316+ }
317+
318+ // Convert AG Grid filters to SQLAlchemy format
319+ const convertedFilters = convertAgGridFiltersToSQL (
320+ filterModel as AgGridFilterModel ,
321+ ) ;
322+
323+ // Log the conversion for debugging
324+ logFilterConversion ( filterModel as AgGridFilterModel , convertedFilters ) ;
325+
326+ setColumnFilters ( filterModel ) ;
327+
328+ // Call the handler to update ownState if server pagination is enabled
329+ if ( onAgGridColumnFiltersChange && serverPagination ) {
330+ onAgGridColumnFiltersChange ( filterModel as AgGridFilterModel ) ;
331+ }
332+ } , [ onAgGridColumnFiltersChange , serverPagination , serverPaginationData ?. agGridFilterModel ] ) ;
333+
334+ // Log filter state whenever it changes
335+ useEffect ( ( ) => {
336+ console . log ( 'Current Filter State:' , columnFilters ) ;
337+ } , [ columnFilters ] ) ;
338+
262339 return (
263340 < div style = { containerStyles } ref = { containerRef } >
264341 < div className = "dropdown-controls-container" >
@@ -303,6 +380,7 @@ const AgGridDataTable: FunctionComponent<AgGridTableProps> = memo(
303380 < ThemedAgGridReact
304381 ref = { gridRef }
305382 onGridReady = { onGridReady }
383+ onFilterChanged = { onFilterChanged }
306384 className = "ag-container"
307385 rowData = { rowData }
308386 headerHeight = { 36 }
0 commit comments