Filter Model & Dash Callbacks

The filter model represents the state of filters for all columns and has the following structure:

# Sample filterModel
{
    'athlete': {
        'filterType': 'text',
        'type': 'startsWith',
        'filter': 'mich'
    },
    'age': {
        'filterType': 'number',
        'type': 'lessThan',
        'filter': 30
    }
}

This is useful if you want to set the filter initially, or save the filter state and apply it at a later stage.
It is also useful when you want to pass the filter state to the server for filtering in a Dash callback.

If you are using AG Grid Enterprise, note that the Set Filter is the default rather than the Text Filter.
For more information, please see the Set Filter section.

Setting the Filter Model in a Callback

This example demonstrates
- Setting the filterModel in a callback with the “Update Filter” button
- Using persistence to maintain user selections when the page is refreshed

```python

import dash
import dash_ag_grid as dag
from dash import Dash, Input, Output, dcc, html, callback

app = Dash()

columnDefs = [
    {"field": "make", "filter":"agTextColumnFilter"},
    {"field": "model", "filter":"agTextColumnFilter"},
    {"field": "price"},
]

rowData = [
    {"make": "Toyota", "model": "Celica", "price": 35000},
    {"make": "Ford", "model": "Mondeo", "price": 32000},
    {"make": "Porsche", "model": "Boxster", "price": 72000},
]


app.layout = html.Div(
    [
        dcc.Markdown(
             "Use the 'Update Filter' button to set the `filterModel` "
         ),
        html.Button("Update Filter", id="filter-model-btn-2", n_clicks=0),
        dag.AgGrid(
            id="filter-model-grid-2",
            columnSize="sizeToFit",
            rowData=rowData,
            columnDefs=columnDefs,
            defaultColDef={"filter": True, "sortable": True, "floatingFilter": True},
            persistence=True,
            persisted_props=["filterModel"]
        ),
    ]
)


@callback(
    Output("filter-model-grid-2", "filterModel"),
    Input("filter-model-btn-2", "n_clicks"),
)
def get_cur_filter(n):
    if n >0:
        return {'model': {'filterType': 'text', 'type': 'contains', 'filter': 'cel'}}
    return dash.no_update


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

Setting the Filter Model when the App Starts

This example demonstrates
- Settings the filter when the app starts
- Accessing the filterModel in a callback

```python
import dash_ag_grid as dag
from dash import Dash, Input, Output, html, callback, dcc


app = Dash()

columnDefs = [
    {"field": "make", "filter":"agTextColumnFilter"},
    {"field": "model", "filter":"agTextColumnFilter"},
    {"field": "price"},
]

rowData = [
    {"make": "Toyota", "model": "Celica", "price": 35000},
    {"make": "Ford", "model": "Mondeo", "price": 32000},
    {"make": "Porsche", "model": "Boxster", "price": 72000},
]


app.layout = html.Div(
        [
            dcc.Markdown("This grid has a filter set initially"),
            dag.AgGrid(
                id="filter-model-grid2",
                columnSize="sizeToFit",
                rowData=rowData,
                columnDefs=columnDefs,
                defaultColDef={"filter": True, "sortable": True, "floatingFilter": True},
                filterModel={'model': {'filterType': 'text', 'type': 'contains', 'filter': 'cel'}}
            ),
            html.Div(id="filter-model-output2"),
        ]
    )


@callback(
    Output("filter-model-output2", "children"),
    Input("filter-model-grid2", "filterModel"),
)
def get_cur_filter(selection_changed):
    return str(selection_changed)



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

Filtered and Sorted Data

This example demonstrates using the virtualRowData in a callback to access filtered and sorted data in a callback..
Note - Use rowData to get the original data.

```python
import dash_ag_grid as dag
from dash import Dash, Input, Output, html, callback, dcc


app = Dash()


columnDefs = [
    {"field": "make"},
    {"field": "model"},
    {"field": "price"},
]

rowData = [
    {"make": "Toyota", "model": "Celica", "price": 35000},
    {"make": "Ford", "model": "Mondeo", "price": 32000},
    {"make": "Porsche", "model": "Boxster", "price": 72000},
]


app.layout = html.Div(
        [
            dcc.Markdown("Demo of accessing grid data after sort and filter"),
            dag.AgGrid(
                id="virtualRowData-grid",
                columnSize="sizeToFit",
                rowData=rowData,
                columnDefs=columnDefs,
                defaultColDef={"filter": True, "sortable": True, "floatingFilter": True},
            ),
            html.Div(id="virtualRowData-output"),
        ]
    )


@callback(
    Output("virtualRowData-output", "children"),
    Input("virtualRowData-grid", "virtualRowData"),
)
def get_data(virtual_data):
    return str(virtual_data)



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

Filter Model Multiple Conditions

Note that as of AG Grid versions 29.2, multiple Filter Conditions are supported.

Each filter’s default filter options can be found on their respective pages:
- Text Filter Options
- Number Filter Options
- Date Filter Options

Here’s an example multiple conditions for the Text Filter on the “sport” column:



filterModel = {
    "sport": {
        "filterType": "text",
        "operator": "OR",
        "conditions": [
            {
                "filter": "Swim",
                "filterType": "text",
                "type": "contains",
            },
            {
                "filter": "Ski",
                "filterType": "text",
                "type": "contains",
            },
            {
                "filter": "Rowing",
                "filterType": "text",
                "type": "contains",
            }
         ]
    }
}

This example shows updating multiple filter options in a callback.

Note that the "suppressHeaderFilterButton": True is set on the Year column. This removes the filter icon from the Year column header so that the Year filter can be set only from the dropdown.

```python
import dash_ag_grid as dag
from dash import Dash, dcc, html, callback, Input, Output, State
import pandas as pd

app = Dash()


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


columnDefs = [
    {"field": "year", "suppressHeaderFilterButton": True, "filterParams": {"maxNumConditions": 7}}
] + [{"field": i} for i in ["athlete", "country", "sport", "total"]]


defaultColDef = {
    "flex": 1,
    "minWidth": 150,
    "filter": "agTextColumnFilter",
}

app.layout = html.Div(
    [
        html.Label("Select Year"),
        dcc.Dropdown(
            years,
            value=years,
            multi=True,
            clearable=False,
            id="dd-filter-model-multiple-conditions",
        ),
        dag.AgGrid(
            columnDefs=columnDefs,
            rowData=df.to_dict("records"),
            defaultColDef=defaultColDef,
            dashGridOptions={"animateRows": False},
            id="grid-filter-model-multiple-conditions",
            filterModel={},
        ),
    ]
)


@callback(
    Output("grid-filter-model-multiple-conditions", "filterModel"),
    Input("dd-filter-model-multiple-conditions", "value"),
    State("grid-filter-model-multiple-conditions", "filterModel"),
)
def update_filter_model(selected_years, model):
    model["year"] = {
        "filterType": "number",
        "operator": "OR",
        "conditions": [
            {"filterType": "number", "type": "equals", "filter": year}
            for year in selected_years
        ],
    }
    return model


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