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:
- If the value is a valid ISO date, the filter is a date filter.
- Else if
parseFloatreturns a finite number within the safe-integer range, the filter is a number filter. - 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
- 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.
- Created; written against the published 0.3.0 package source, not the README.