Filter Expressions
A rule's FilterText is the condition that decides, per item, whether the
match values or the no-match values are written. It is parsed by the shared
TTMSFNCFilterBuilder engine — the
same engine the TMS FNC Dataset uses for row
filtering — so the syntax is consistent across the product. Write expressions
by hand when you need operators, grouping, or runtime values that the one-line
ShowWhere/AddRuleEquals helpers do not express. This guide covers the
expression syntax, how field names map to item properties, forcing a field's
data type, and substituting live values through {Placeholder} text sources.
Expression syntax
FilterText reads like a SQL WHERE clause:
- Field references are wrapped in square brackets —
[Status],[Order Date]. The brackets are the column delimiter, so they are required even for simple names (a bare or double-quoted name is not recognised as a field and silently matches nothing). - String literals use single quotes:
'Open'.LIKEaccepts the%wildcard:[Name] LIKE 'A%'. - Operators mirror the
TTMSFNCFilterBuilderExpressionOperatorset:=,<>,>,<,>=,<=, andLIKE, plus empty/not-empty tests. - Grouping combines conditions with
ANDandORand parentheses:([Price] >= 100 AND [Stock] > 0) OR [Featured] = 1.
An empty FilterText matches every item unconditionally — useful when the rule
exists only to push inactive values or to be filled in later.
Expression format
The syntax above is the default Delphi DataSet format, which mirrors a
dataset filter: bracketed field names, single-quoted strings, LIKE with
%/_ wildcards, and AND/OR keywords. The shared
TTMSFNCFilterBuilder also
understands an OData format — useful when you need to exchange filter
expressions with a web API or backend that speaks OData v4. Field names are
bare (no brackets), string functions replace wildcards, and the logical
operators are lowercase keywords:
| Condition | Delphi DataSet | OData |
|---|---|---|
| Equals (text) | [Name] LIKE 'Open' |
Name eq 'Open' |
| Starts with | [Name] LIKE 'A%' |
startswith(Name, 'A') |
| Ends with | [Name] LIKE '%z' |
endswith(Name, 'z') |
| Contains | [Name] LIKE '%A%' |
contains(Name, 'A') |
| Greater than | [Price] > 100 |
Price gt 100 |
| Is empty | [Status] = '' |
Status eq null |
| And / Or | AND / OR |
and / or |
Write rule expressions in the Delphi DataSet format for local filtering. Use
the OData format when generating or consuming filter strings for a remote API.
To switch the engine to OData mode, set FormatType to fftOData on the
TTMSFNCFilterBuilder instance the
manager uses.
Field names and item paths
Field names in the expression are resolved as RTTI properties on each item that
ItemsPath yields. ItemsPath itself is an RTTI path navigated from Source:
Items[*] evaluates every element of an Items collection, Items[1..3|5]
selects specific indices, and an empty path targets Source directly. The
field name in FilterText must match a readable property on the resolved item.
Overriding a field's data type
The builder normally infers a field's type from its value. When a value would
be read as the wrong type — a numeric code stored as text, a date that should
sort chronologically — add a TTMSFNCFilterRuleFieldTypes
entry to pin it. FieldTypes.Add(name, type) takes a
TTMSFNCFilterBuilderDataType such
as fdtNumber, fdtDate, fdtBoolean, or fdtText (the default is
fdtAutomatic).
uses
TMS.TMSFNCFilterRulesManager, TMS.TMSFNCFilterBuilder;
{ Inside a method of your form: }
var
Rule: TTMSFNCFilterRule;
begin
Rule := FilterRulesManager1.AddRule('Expensive', Grid1, 'Items[*]', '');
// Field references use [brackets]; string literals use single quotes and
// LIKE accepts the % wildcard.
Rule.FilterText := '[Price] >= 1000 AND [Name] LIKE ''A%''';
// The builder auto-detects types from the value, but you can force one when
// the field text would otherwise be read as the wrong type.
Rule.FieldTypes.Add('Price', fdtNumber);
Rule.AddVisibilityAction(True);
FilterRulesManager1.Apply;
end;
Placeholder text sources
To filter against a value that changes at runtime — text typed into a search
box, a selected combo item — bind a placeholder through the manager's
Placeholders collection (a
TTMSFNCFilterRulePlaceholders).
Text sources are defined once on the manager and shared across every rule.
Write {PlaceholderName} anywhere in a rule's FilterText (or in ItemsPath);
at each Apply, every occurrence is replaced with the current value of the bound
Source.PropertyName before the expression is evaluated. This keeps the rule
fixed while the value it tests against follows the UI.
Combining a placeholder with a typed field
A live search usually combines both features: a placeholder feeds the text part
of the filter while a FieldTypes override keeps a numeric condition correct.
Re-call Apply whenever the bound control changes:
uses
TMS.TMSFNCFilterRulesManager, TMS.TMSFNCFilterBuilder;
{ Inside a method of your form, with an edit named SearchEdit: }
var
Rule: TTMSFNCFilterRule;
begin
Rule := FilterRulesManager1.AddRule('LiveSearch', Grid1, 'Items[*]', '');
// Bind {SearchText} to SearchEdit.Text. Text sources live on the manager and
// are shared across every rule; the token is substituted at Apply.
FilterRulesManager1.AddPlaceholder('SearchText', SearchEdit, 'Text');
// The placeholder appears inside the expression; a typed field keeps the
// numeric comparison correct.
Rule.FilterText := '[Name] LIKE ''{SearchText}%'' AND [Stock] > 0';
Rule.FieldTypes.Add('Stock', fdtNumber);
Rule.AddVisibilityAction(True);
FilterRulesManager1.Apply; // re-call Apply whenever SearchEdit changes
end;
Common pitfalls
- Brackets for fields, single quotes for strings.
[Name] = 'Open'is correct. A field reference must be bracketed:"Name"or a bareNameis not recognised as a column and the expression silently matches nothing. - The field must be readable on the item. A bracketed name in
FilterTextwith no matching item property resolves to nothing and never matches. - Placeholders are substituted as text.
{SearchText}is spliced into the expression literally, so wrap it in quotes and wildcards as needed (LIKE '{SearchText}%'). Re-callApplyfor the new value to take effect. - Pin the type when auto-detection guesses wrong. A code like
007read as a number loses its leading zeros — forcefdtTextviaFieldTypes.
See also
- Rules and actions — what happens once an item matches
- Upsert helpers — operator shortcuts that build the expression for you
TTMSFNCFilterBuilderTTMSFNCFilterRuleFieldTypesTTMSFNCFilterRulePlaceholders