Applicability Gate
Some rules apply only to a subset of elements, and that subset is determined not by a simple field check but by a computed result — for example, a shared parameter that exists and has a value. The applicability gate is the pattern for keeping such elements out of the validator's scope.
The problem
A validator checks a field value. But if the field does not exist or the check does not apply, you do not want the element in the output at all. Including it would cause false positives.
The pattern
Compute a boolean field in the projection, then filter on it after the projection using [condition]:
$[type = "FamilyInstance"].(
$applicable := $exists(values.mark) and values.mark != null;
{
"id": id,
"name": name,
"mark": values.mark,
"checkApplicable": $applicable
}
)[checkApplicable = true]
Only elements where checkApplicable = true appear in the output. Elements where the condition is false are silently dropped.
The validator then only sees elements that are in scope, so there is no risk of a false positive from an element that was never applicable.
With a shared parameter
Shared parameters have an exists and hasValue field. The gate keeps only elements where the parameter is present and filled:
$[type = "FamilySymbol"].(
$sp := $getSharedParam($, "NLRS_C_kwaliteitsklasse_code");
{
"id": id,
"name": name,
"paramValue": $sp.valueAsString,
"checkApplicable": $sp.exists and $sp.hasValue
}
)[checkApplicable = true]
Inverting the gate — surface only the missing
To expose elements where the parameter is absent (for a "must exist" check), invert the condition:
$[type = "FamilyInstance"].(
$applicable := $not($exists(values.mark));
{
"id": id,
"name": name,
"checkApplicable": $applicable
}
)[checkApplicable = true]
This outputs only elements where mark is missing — the validator then simply checks that the output is empty.
Gate vs filter predicate
Both $[condition] and [condition] filter elements. The difference is when the condition is evaluated:
Filter predicate $[...] |
Applicability gate [...] |
|
|---|---|---|
| Position | Before the projection | After the projection |
| Reads computed fields? | No — those don't exist yet | Yes |
| Reads raw object fields? | Yes | Yes |
Use a filter predicate when the condition depends only on raw data. Use the applicability gate when the condition depends on a computed field in the projection.
Common mistakes
- Using the gate but forgetting to compute the field — if
checkApplicableis missing from the projection, the[checkApplicable = true]filter drops everything - Placing the gate before the projection — the computed field does not exist yet at that point