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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Links "DE#nnn" prior to version 2.0 point to the Dash Enterprise closed-source D
- [#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)
- fixes [#407](https://github.com/plotly/dash-ag-grid/issues/407)
- [#412](https://github.com/plotly/dash-ag-grid/issues/412) fix "Multi-Column Filter not properly recognized in filterParams"

## [33.3.2rc2] - 2025-09-17

Expand Down
1 change: 1 addition & 0 deletions src/lib/utils/propCategories.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ export const COLUMN_NESTED_OR_OBJ_OF_FUNCTIONS = {
export const COLUMN_ARRAY_NESTED_FUNCTIONS = {
children: 1,
filterOptions: 1,
filters: 1,
};

/**
Expand Down
38 changes: 37 additions & 1 deletion tests/assets/dashAgGridFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,41 @@ dagfuncs.startWith = ([filterValues], cellValue) => {
const name = cellValue ? cellValue.split(" ")[1] : ""
return name && name.toLowerCase().indexOf(filterValues.toLowerCase()) === 0
}

dagfuncs.dateFilterComparator = (filterLocalDateAtMidnight, cellValue) => {
const dateAsString = cellValue;

if (dateAsString == null) {
// Return -1 to show nulls "before" any date
return -1;
}

// The data from this CSV is in dd/mm/yyyy format
const dateParts = dateAsString.split("/");
if (dateParts.length !== 3) {
// Handle invalid format
return 0;
}

const day = Number(dateParts[0]);
const month = Number(dateParts[1]) - 1; // JS months are 0-indexed
const year = Number(dateParts[2]);
const cellDate = new Date(year, month, day);

// Check for invalid date (e.g., from "NaN")
if (isNaN(cellDate.getTime())) {
return 0;
}

// Now that both parameters are Date objects, we can compare
if (cellDate < filterLocalDateAtMidnight) {
return -1;
} else if (cellDate > filterLocalDateAtMidnight) {
return 1;
}
return 0;
};

// END test_custom_filter.py

// FOR test_quick_filter.py
Expand Down Expand Up @@ -502,4 +537,5 @@ dagfuncs.TestEvent = (params, setEventData) => {

dagfuncs.testToyota = (params) => {
return params.data.make == 'Toyota' ? {'color': 'blue'} : {}
}
}

98 changes: 98 additions & 0 deletions tests/test_custom_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,101 @@ def test_fi005_custom_filter(dash_duo):
# Test numberParser and numberFormatter
grid.set_filter(0, "$100,5")
grid.wait_for_cell_text(0, 0, "$200,00")

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

df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)

columnDefs = [
{"field": "athlete",
"filter": "agMultiColumnFilter",
"filterParams": {
"filters": [
{"filter": "agTextColumnFilter"},
{"filter": "agSetColumnFilter"} # Example with Set Filter
]
}},
{"field": "country"},
{
"field": "date",
"filter": "agMultiColumnFilter",
"filterParams": {
"filters": [
{
"filter": "agSetColumnFilter",
'filterParams': {'excelMode': 'windows', 'buttons': ['apply', 'reset'],
}
},
{
"filter": "agDateColumnFilter",
'filterParams': {
'excelMode': 'windows',
'buttons': ['apply', 'reset'],
'comparator': {'function': 'dateFilterComparator'},
}
},
],

},
},
]


app.layout = html.Div(
[
dag.AgGrid(
id="date-filter-example",
enableEnterpriseModules=True,
columnDefs=columnDefs,
rowData=df.to_dict("records"),
defaultColDef={"flex": 1, "minWidth": 150, "floatingFilter": True},
dashGridOptions={"animateRows": False}
),
],
)

dash_duo.start_server(app)

grid = utils.Grid(dash_duo, "date-filter-example")

grid.wait_for_cell_text(0, 0, "Michael Phelps")

# Test Set Filter - click filter button on date column
dash_duo.find_element('.ag-floating-filter[aria-colindex="3"] button').click()

# Uncheck "Select All"
dash_duo.find_element('.ag-set-filter-list .ag-set-filter-item .ag-checkbox-input').click()

# Select "24/08/2008"
dash_duo.wait_for_element('.ag-set-filter-list .ag-virtual-list-item', timeout=10)
set_filter_items = dash_duo.find_elements('.ag-set-filter-list .ag-virtual-list-item')
checkboxes = dash_duo.find_elements('.ag-set-filter-list .ag-virtual-list-item .ag-checkbox-input')

for i, item in enumerate(set_filter_items):
if "24/08/2008" in item.text:
checkboxes[i].click()
break

# Apply
dash_duo.find_element('button[data-ref="applyFilterButton"]').click()
grid.wait_for_cell_text(0, 2, "24/08/2008")

# Reset
dash_duo.find_element('.ag-floating-filter[aria-colindex="3"] button').click()
dash_duo.find_element('button[data-ref="resetFilterButton"]').click()

# Test Date Filter - click filter button again
dash_duo.find_element('.ag-floating-filter[aria-colindex="3"] button').click()

# Type date
date_input = dash_duo.find_element('.ag-filter-wrapper .ag-date-filter input[class="ag-input-field-input ag-text-field-input"]')
date_input.click()
date_input.send_keys("24-08-2008")

# Apply
apply_buttons = dash_duo.find_elements('button[data-ref="applyFilterButton"]')
apply_buttons[1].click()
grid.wait_for_cell_text(0, 2, "24/08/2008")