Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ This project adheres to [Semantic Versioning](https://semver.org/).
Links "DE#nnn" prior to version 2.0 point to the Dash Enterprise closed-source Dash AG Grid repo

## [unreleased]

### Added
- [#436](https://github.com/plotly/dash-ag-grid/pull/436) Enabled Filter Handlers to simplify custom filter components by splitting the filter logic out from the UI component.

## [34.0.0rc0] - 2026-01-21
### Fixed
- [#408](https://github.com/plotly/dash-ag-grid/pull/408) fixed issue where the `columnState` would conflict with `columnDefs` updates
- fixes [#416] (https://github.com/plotly/dash-ag-grid/issues/416)
Expand Down
4 changes: 3 additions & 1 deletion src/lib/fragments/AgGrid.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,9 @@ export function DashAgGrid(props) {
if (has('function', value)) {
return convertMaybeFunctionNoParams(value);
}
return convertCol(value);
if (typeof value === 'object') {
return convertCol(value);
}
}
// not one of those categories - pass it straight through
return value;
Expand Down
6 changes: 5 additions & 1 deletion src/lib/utils/propCategories.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,17 @@ export const GRID_NESTED_FUNCTIONS = {
**/
export const COLUMN_MAYBE_FUNCTIONS_NO_PARAMS = {
cellEditor: 1,
filter: 1,

// Columns: Sort
comparator: 1,
pivotComparator: 1,

// filter params custom option
predicate: 1,

// filter
doesFilterPass: 1,
handler: 1,
};

/**
Expand Down Expand Up @@ -299,6 +302,7 @@ export const COLUMN_NESTED_OR_OBJ_OF_FUNCTIONS = {
**/
export const COLUMN_NESTED_OR_OBJ_OF_FUNCTIONS_NO_PARAMS = {
filterParams: 1,
filter: 1,
};

/**
Expand Down
29 changes: 28 additions & 1 deletion tests/assets/dashAgGridComponentFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,31 @@ dagcomponentfuncs.myCustomButton2 = function (props) {
className: props.value.className,

}, 'test cellRendererData'))
}
}


dagcomponentfuncs.YearFilter34 = (props) => {
const [year, setYear] = useState('All');

useEffect(() => {
props.onModelChange(year === "All" ? null : year)
}, [year]);

setProps = ({value}) => {
if (value) {
setYear(value)
}
}

return React.createElement(
window.dash_core_components.RadioItems,
{
options: [
{'label': 'All', 'value': 'All'},
{'label': 'Since 2010', 'value': '2010'},
],
value: year,
setProps
}
)
};
6 changes: 6 additions & 0 deletions tests/assets/dashAgGridFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,12 @@ dagfuncs.YearFilter = forwardRef((props, ref) => {
)
});


// for v34 filter logic seperate from component
dagfuncs.doesFilterPass = (params) => {
return params.data.year >= 2010;
}

dagfuncs.setBody = () => {
return document.querySelector('body')
}
Expand Down
61 changes: 61 additions & 0 deletions tests/test_custom_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,67 @@ def test_fi003_custom_filter(dash_duo):
grid.wait_for_cell_text(0, 0, "23")


def test_fi003_custom_filter_v34(dash_duo):
app = Dash(__name__)

df = pd.read_json('https://www.ag-grid.com/example-assets/olympic-winners.json', convert_dates=False)

rowData = df.to_dict('records')

columnDefs = [
{'field': 'age', 'filter': 'agNumberColumnFilter'},
{'field': 'country', 'minWidth': 150},
{'field': 'year', 'filter': {'component': 'YearFilter34', 'doesFilterPass': {'function': 'doesFilterPass'}}},
{
'field': 'date',
'minWidth': 130,
'filter': 'agDateColumnFilter',
},
{'field': 'sport'},
{'field': 'gold', 'filter': 'agNumberColumnFilter'},
{'field': 'silver', 'filter': 'agNumberColumnFilter'},
{'field': 'bronze', 'filter': 'agNumberColumnFilter'},
{'field': 'total', 'filter': 'agNumberColumnFilter'},
]

defaultColDef = {
'editable': True,
'sortable': True,
'flex': 1,
'minWidth': 100,
'filter': True,
'resizable': True,
}

app.layout = html.Div(
[
dag.AgGrid(
id="grid",
columnDefs=columnDefs,
rowData=rowData,
defaultColDef=defaultColDef,
dashGridOptions={"enableFilterHandlers": True}
),
]
)

dash_duo.start_server(app)

grid = utils.Grid(dash_duo, "grid")

grid.wait_for_cell_text(0, 0, "23")

dash_duo.find_element('.ag-header-cell[aria-colindex="3"] span[data-ref="eFilterButton"]').click()

dash_duo.find_element('.ag-filter label:nth-child(2)').click()

grid.wait_for_cell_text(0, 0, "27")

dash_duo.find_element('.ag-filter label:nth-child(1)').click()

grid.wait_for_cell_text(0, 0, "23")


# test filterParams.textFormatter, filterParams.textMatcher and filterParams.filterOptions.predicate functions
def test_fi004_custom_filter(dash_duo):
app = Dash(__name__)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_infinite_scroll.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,9 @@ def infinite_scroll(request):
grid.get_header_cell(0).click()
grid.wait_for_cell_text(0, 0, "9999")
grid.get_header_cell(1).click()
grid.wait_for_cell_text(1, 0, "3600")
grid.wait_for_cell_text(0, 1, "0-0-0")
grid.get_header_cell(1).click()
grid.wait_for_cell_text(0, 0, "7263")
grid.wait_for_cell_text(0, 1, "4-6-7")


def test_is002_infinite_scroll_styling(dash_duo):
Expand Down