ag-grid-url-sync: the query-string grammar

A filter in ag-grid-url-sync is one query parameter: f_ prefix, column id, underscore, operation token, =, value. So f_salary_gte=80000 means the salary column is filtered to values of 80,000 or more. 18 tokens cover all 26 AG Grid text, number and date operations, because four tokens are shared across types. This page is the grammar for version 0.3.0.

One parameter per column, split on the last underscore

The parameter name is <prefix><column>_<operation>. The prefix defaults to f_ and is configurable; the parser adds a trailing underscore if the configured prefix lacks one. Everything after the prefix is split on the last underscore, so column ids may contain underscores and operation tokens never do. f_first_name_startsWith=jo parses as column first_name, operation startsWith, value jo.

Parameters that do not start with the prefix are ignored, so the filter parameters can share a URL with anything else. Each column appears once; the grammar has no way to express two conditions on one column, and no AND/OR operator. A parameter that fails to parse is reported through the onParseError callback and skipped, and parsing continues with the rest.

The 18 operation tokens

Internal operation names are longer than the tokens in the URL. The token is what you type; the internal name is what the library’s TypeScript types use; the AG Grid name is what reaches the grid’s filter model.

Token Internal name AG Grid name Applies to
contains contains contains text
notContains notContains notContains text
startsWith startsWith startsWith text
endsWith endsWith endsWith text
eq eq equals text, number, date
neq notEqual notEqual text, number, date
blank blank blank text, number, date
notBlank notBlank notBlank text, number, date
lt lessThan lessThan number
lte lessThanOrEqual lessThanOrEqual number
gt greaterThan greaterThan number
gte greaterThanOrEqual greaterThanOrEqual number
range inRange inRange number
before dateBefore lessThan date
beforeEq dateBeforeOrEqual lessThanOrEqual date
after dateAfter greaterThan date
afterEq dateAfterOrEqual greaterThanOrEqual date
daterange dateRange inRange date

Counting per type gives AG Grid’s 26: 8 text, 9 number and 9 date, with eq, neq, blank and notBlank counted once per type. Every token matches its internal name except the eleven shortened ones, and eq is the only token that AG Grid itself spells differently, as equals.

Date operations reuse AG Grid’s comparison names because AG Grid’s date filter has no before or after of its own. The URL grammar introduces those words so a link reads as a sentence: f_deadline_before=2026-12-31.

Values: text is encoded, numbers and dates are not

Text values are passed through encodeURIComponent when a URL is generated, so f_name_contains=O%27Brien is the encoded form of O'Brien. On parsing, the value is taken as-is from the URL’s search parameters and checked against a maximum length, 200 characters by default and configurable through maxValueLength. Anything longer is a parse error.

Number values must match a strict pattern: an optional sign, digits with an optional fraction, or a leading-dot fraction, and an optional exponent. 42, -3.5, .5 and 1e6 pass. 42abc fails, because the library checks the pattern before calling parseFloat, which would otherwise accept it. An empty value fails. The magnitude must not exceed Number.MAX_SAFE_INTEGER. Numbers are written without encoding.

Date values must be exactly YYYY-MM-DD, ten characters. The library then constructs the date in UTC and checks that year, month and day round-trip, so 2026-02-30 is rejected even though Date would silently roll it into March. Dates are written without encoding; the hyphens are safe.

Blank operations ignore the value. The generator writes =true, so f_notes_blank=true, and the parser accepts any value or none. The filter applied to the grid carries an empty string.

Ranges use a comma and exactly two parts

range and daterange take min,max and start,end. The comma is written literally, not encoded, and the parser splits on it and requires exactly two parts. Each part is validated by the number or date rule above, and the first value must be no greater than the second, for numbers and for dates.

f_age_range=25,45
f_period_daterange=2026-01-01,2026-12-31

A range with one part, three parts, or an empty side is a parse error for that column only. Date ranges reach the grid as inRange with dateFrom and dateTo; number ranges as inRange with filter and filterTo.

Shared tokens infer their type from the value

eq, neq, blank and notBlank are valid on text, number and date columns, and the URL does not say which. The parser decides from the value, in this order:

  1. If the value is a valid ISO date, the filter is a date filter.
  2. Else if parseFloat returns a finite number within the safe-integer range, the filter is a number filter.
  3. Else it is a text filter.

blank and notBlank always parse as text filters, since there is no value to inspect. Two consequences follow. f_status_eq=2026-01-15 on a text column parses as a date filter, and f_id_eq=42abc parses as a number filter with value 42, because step 2 uses parseFloat and not the strict pattern the number-only tokens use. In practice the grid’s own column definition decides how the value is used, so both cases behave when the column type matches the value, and the detection only matters when it does not.

Grouped mode packs every filter into one parameter

The default is one parameter per column, called individual mode. Grouped mode instead writes a single parameter, grid_filters by default and configurable through groupedParam, in one of three formats:

Format What the value holds Example, decoded
querystring (default) The individual-mode string, percent-encoded once more f_name_contains=john&f_age_gt=25
json The library’s filter-state object as JSON {"name":{"filterType":"text","type":"contains","filter":"john"}}
base64 The JSON format, base64-encoded eyJuYW1lIjp7...

The querystring format is the same grammar as this page, so a grouped URL is readable once decoded. The JSON format uses the internal operation names from the table above, not the URL tokens: "type":"greaterThan", not "type":"gt". On parsing, the library checks for a grouped parameter first and detects its format, trying base64 before JSON before querystring; if none is present it falls back to individual mode. A URL cannot mix the two.

What the grammar does not cover

Only the three column filter types are encoded. The grammar has no form for AG Grid’s set filter, for multi-condition filters joined with AND or OR, for the floating-filter state, or for sort order and column arrangement. Those are out of scope by design: the library is for sharing a filtered view as a link, and a link that also pinned column widths would break the moment the recipient’s grid differed.

The columns it applies to are detected from the grid’s own definitions: agTextColumnFilter, agNumberColumnFilter and agDateColumnFilter first, then cellDataType of date, number or text. A parameter naming a column the grid does not have parses successfully and is skipped when the filters are applied.

Version and stability

This page describes version 0.3.0, the current release on npm, and was written from the published package source rather than the README. When the grammar changes, this page is revised and the revision log says what moved.

Revisions

  1. Published. Defaults and the 18 tokens re-checked against the 0.3.0 package, still the current npm release; added a link to the URL-as-state essay.
  2. Created; written against the published 0.3.0 package source, not the README.