External Filter

External filtering allows you to mix your own filtering logic with the grid’s inbuilt filtering, without creating
column-based filter components.

This form of filtering is only compatible with
the Client-Side Row Model, see Row Models for more details.

Implementing External Filtering

The example below shows external filters in action. There are two methods on dashGridOptions you need to implement:
isExternalFilterPresent and doesExternalFilterPass.

isExternalFilterPresent

isExternalFilterPresent is called exactly once every time the grid senses a filter change. It should return True if
external filtering is active or False otherwise. If you return True, doesExternalFilterPass will be called while
filtering, otherwise doesExternalFilterPass will not be called.

doesExternalFilterPass

doesExternalFilterPass is called once for each row node in the grid. If you return False, the node will be excluded
from the final set.

External Filter Example

The example below shows an external filter in action.

View the JavaScript functions used for this example.

These JavaScript functions must be added to the dashAgGridFunctions.js file in the assets folder.
See JavaScript Functions
for more information.

var dagfuncs = (window.dashAgGridFunctions = window.dashAgGridFunctions || {});

dagfuncs.dateAfter2008 = (params) => {
    const splitFields = params.data.date.split('/');

    const date = new Date(
        Number.parseInt(splitFields[2]),
        Number.parseInt(splitFields[1]) - 1,
        Number.parseInt(splitFields[0])
    );

    return date > new Date(2008, 1, 1)
};

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

    if (dateAsString == null) {
        return 0;
    }

    // In the example application, dates are stored as dd/mm/yyyy
    // We create a Date object for comparison against the filter date
    const dateParts = dateAsString.split("/");
    const year = Number(dateParts[2]);
    const month = Number(dateParts[1]) - 1;
    const day = Number(dateParts[0]);
    const cellDate = new Date(year, month, day);

    // Now that both parameters are Date objects, we can compare
    if (cellDate < filterLocalDateAtMidnight) {
        return -1;
    } else if (cellDate > filterLocalDateAtMidnight) {
        return 1;
    }
    return 0;
};
```python
import dash_ag_grid as dag
from dash import Dash, html, dcc, Input, Output, callback
import pandas as pd

app = Dash()

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

columnDefs = [
    {"field": 'athlete', "minWidth": 180},
    {"field": 'age', "filter": 'agNumberColumnFilter', "maxWidth": 80},
    {"field": 'country'},
    {"field": 'year', "maxWidth": 90},
    {
        "field": 'date',
        "filter": 'agDateColumnFilter',
        "filterParams": {
            "comparator": {"function": "dateFilterComparator"},
        },
    },
]

filter_function = {
    'below25': "params.data.age < 25",
    'between25and50': "params.data.age >= 25 && params.data.age <= 50",
    'above50': "params.data.age > 50",
    'dateAfter2008': "dateAfter2008(params)",
    'everyone': "true"
}

app.layout = html.Div(
    [
        dcc.RadioItems(
            id='external-filter-radio',
            options={
                'everyone': 'Everyone',
                'below25': 'Below 25',
                'between25and50': 'Between 25 and 50',
                'above50': 'Above 50',
                'dateAfter2008': 'After 01/01/2008',
            },
            value='everyone',
            inline=True,
            style={'margin': '10px'}
        ),
        dag.AgGrid(
            id="external-filter-example",
            rowData=df.to_dict("records"),
            columnDefs=columnDefs,
            defaultColDef={"flex": 1},
        ),
    ]
)


@callback(
    Output("external-filter-example", "dashGridOptions"),
    Input("external-filter-radio", "value"),
    prevent_initial_call=True,
)
def update_external_filter(filter_value):
    return {
        # if filter_value is not 'everyone', then we are filtering
        "isExternalFilterPresent": {"function": "true" if filter_value != 'everyone' else "false"},
        "doesExternalFilterPass": {"function": filter_function[filter_value]}
    }


if __name__ == "__main__":
    app.run(debug=True)
```