InterviewsVector

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) — like ngOnInit; stash the IFilterParams (it carries filterChangedCallback and getValue).
  • isFilterActive() — return whether the filter is on. This drives the column's filter icon and whether the grid bothers calling doesFilterPass.
  • doesFilterPass(params) — return true for rows that should stay.
  • getModel() / setModel(model) — serialise/restore the filter state (for api.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() returns false, so the grid skips doesFilterPass entirely.
  • 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 implement IFilterAngularComp, not a base class.
  • Reading the cell value wrong — use this.params.getValue(params.node) so value getters/formatters are respected.

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.

By Mohammad Wasi

Software Engineering Leader & Technical Author · Updated August 26, 2026


Related Posts