Custom Filter in AG Grid (Angular): A Complete IFilterAngularComp Example
Quick answer
In AG Grid with Angular, a custom filter is a component that implements IFilterAngularComp with four required methods: agInit (receive params), isFilterActive (whether the filter is on — drives the header icon and whether the grid applies it), doesFilterPass (return true for rows that match), and getModel/setModel (serialise the filter state). Register it by setting the column's filter property to the component class, and call params.filterChangedCallback() whenever the UI changes so the grid re-evaluates rows.
Short answer: A custom AG Grid filter in Angular is a component implementing IFilterAngularComp with four required methods — agInit, isFilterActive, doesFilterPass, and getModel/setModel. Register it by setting the column's filter to the component class, and call params.filterChangedCallback() whenever the UI changes.
AG Grid's built-in filters cover most cases, but sometimes you need custom UI or matching logic. In Angular you build that as a component implementing IFilterAngularComp — not the outdated "extend a base class and return a template string" pattern you'll still find in old posts.
The four required methods
agInit(params)— likengOnInit; stash theIFilterParams(it carriesfilterChangedCallbackandgetValue).isFilterActive()— return whether the filter is on. This drives the column's filter icon and whether the grid bothers callingdoesFilterPass.doesFilterPass(params)— returntruefor rows that should stay.getModel()/setModel(model)— serialise/restore the filter state (forapi.getFilterModel()and saved views).
A complete "contains text" filter
import { Component } from "@angular/core"
import { FormsModule } from "@angular/forms"
import { IFilterAngularComp } from "ag-grid-angular"
import { IDoesFilterPassParams, IFilterParams } from "ag-grid-community"
@Component({
standalone: true,
imports: [FormsModule],
template: `
<div class="ag-filter-body-wrapper" style="padding: 8px">
<input
type="text"
[(ngModel)]="text"
(ngModelChange)="onChange()"
placeholder="Contains…"
aria-label="Filter text"
/>
</div>
`,
})
export class ContainsFilterComponent implements IFilterAngularComp {
private params!: IFilterParams
text = ""
agInit(params: IFilterParams): void {
this.params = params
}
isFilterActive(): boolean {
return this.text.trim() !== ""
}
doesFilterPass(params: IDoesFilterPassParams): boolean {
const value = this.params.getValue(params.node) as string | null
return (value ?? "").toLowerCase().includes(this.text.toLowerCase())
}
getModel() {
return this.isFilterActive() ? { text: this.text } : null
}
setModel(model: { text: string } | null): void {
this.text = model?.text ?? ""
}
onChange(): void {
// Tell the grid the filter changed so it re-runs doesFilterPass.
this.params.filterChangedCallback()
}
}Register it on the column
Pass the component class directly:
columnDefs: ColDef[] = [
{ field: "name", filter: ContainsFilterComponent },
{ field: "country" },
]Common interview / debugging traps
- Filter never applies —
isFilterActive()returnsfalse, so the grid skipsdoesFilterPassentirely. - UI updates but rows don't — you forgot
params.filterChangedCallback(). - Using the old
getGui()-returns-a-string API — in Angular the template is the GUI; you implementIFilterAngularComp, not a base class. - Reading the cell value wrong — use
this.params.getValue(params.node)so value getters/formatters are respected.
Related guides
Sources
Key takeaways
- •Implement IFilterAngularComp, not a BaseFilter class — the old extends-Component/getGui-string API is outdated.
- •Required methods: agInit, isFilterActive, doesFilterPass, getModel, setModel.
- •Register by passing the component CLASS to colDef.filter (e.g. filter: ContainsFilterComponent).
- •Call params.filterChangedCallback() whenever the filter UI changes, or the grid won't re-filter.
- •isFilterActive controls the header filter icon AND whether the grid applies doesFilterPass at all.
Frequently asked questions
How do I create a custom filter in AG Grid with Angular?
Write an Angular component that implements IFilterAngularComp. Store the params in agInit, return whether the filter is on from isFilterActive, decide per-row matching in doesFilterPass, and serialise state in getModel/setModel. Register it by setting the column definition's filter property to the component class, and call params.filterChangedCallback() when the UI changes.
Why isn't my custom AG Grid filter applying?
Two usual causes: isFilterActive returns false (so the grid skips your filter entirely), or you never call params.filterChangedCallback() after the UI changes (so the grid never re-runs doesFilterPass). Both must be correct for filtering to take effect.
How do I register a custom filter on a column?
In modern AG Grid you pass the component class directly: { field: 'name', filter: ContainsFilterComponent }. The older approach of registering a string key in gridOptions.components and setting filter: 'myFilter' still works but the class form is simpler.
Software Engineering Leader & Technical Author · Updated August 26, 2026