Rules & Conditions
Rules change form behavior based on field values: showing, locking, calculating, and blocking save.
How Rules Work
A rule consists of a trigger, conditions, and actions. When the conditions are met, all actions of the rule execute. When the conditions stop being met, fields revert to their default state (such as defaultVisible) because continuous rules are recalculated from scratch each time.
- Trigger specifies when the rule is evaluated (continuously, on load, on save). See Rule Triggers.
- Conditions compare a field to a value using operators. In addition to form fields, you can use two system fields:
$formMode(modenew,edit,display) and$userGroups(SharePoint groups of the signed-in user, matched by group name). - Actions modify a field, section, tab, banner, or the entire form. See Rule Actions.
Condition Matching: All or Any
The matchType property controls how conditions are combined:
all("all match" in the editor): the rule applies when every condition is true (AND).any("any matches" in the editor): the rule applies when at least one condition is true (OR).
A rule must have at least one condition and at least one action. The exception is rules with the onLoad or onSave trigger without conditions, which always apply.
Condition Groups
For logic such as (A and also B) or (C or D), click + Group in the WHEN block. The existing conditions become the first group and a second group is added. Each group has its own "all match / at least one matches" toggle; the Between groups toggle combines the groups (default "at least one matches", i.e. OR). Remove a group with the bin icon; removing the last condition of a group removes the group. When one group is left, the rule returns to the simple form without losing conditions. The "Reads as" sentence shows groups in parentheses.
In JSON this is the optional conditionGroups array ([{ "matchType": "all", "conditions": [...] }]) and groupMatchType (all / any, default any). A non-empty conditionGroups takes precedence over conditions; old rules keep working as a single group.
Action Targets
| Target | Format in targetFieldInternalName | Allowed Actions |
|---|---|---|
| Field or widget | internal field name, e.g. Cena | setVisible, setRequired, setReadOnly, setValue, setExpression, blockSave (onSave only) |
| Banner | internal name of the Banner widget | setVisible, setBannerIntent, setBannerTitle, setBannerContent |
| Tab | tab:<tab id> | setVisible, setReadOnly, setColor |
| Section | section:<section id> | setVisible, setReadOnly, setCollapsed, setColor |
| Entire form | $form | blockSave |
| Scripts | $script | callFunction |
The editor offers only actions valid for the selected target. When you change the target, an existing action is converted to the closest allowed action. A rule saved with an invalid combination (such as setCollapsed on a field) is rejected by configuration validation.
Tab and Section Inheritance
Hiding or locking a tab or section propagates to all fields inside it:
- a field inside a hidden tab or section is hidden; a field inside a locked tab or section is read-only;
- a field placed in multiple sections remains visible (editable) if at least one of its placements is visible (editable).
Tabs and sections also have their own visibility conditions and field-driven colors. These are configured in the layout (see Form Layout), not in rules, and are evaluated before rules.
Tokens @Me and @Today
@Mein a condition compares the field against the signed-in user (by ID, email, login name, or display name). Works withequals,contains,notEquals,notContains,isEmpty,isNotEmpty.@Mein the value of setValue fills a Person field with the current user (as a single-item array for multi-value fields), or their display name for other fields.@Todayin the value ofsetValueinserts today's date inYYYY-MM-DDformat.@Todayalso works in condition values: it represents today's date and compares dates without time (a field value2026-06-15T09:00equals today on June 15, 2026). Useequals,notEquals,greaterThan(after today), andlessThan(before today). More complex calculations (day differences) are handled by an expression.
Form Mode
In Display mode (display), all fields are read-only and non-required regardless of rules. Rules still evaluate so hiding and colors continue to work. Values set by rules or scripts in Display mode never mark the form as dirty. To restrict a rule to a mode, add a condition on $formMode.
Evaluation Order
- For each field, section, and tab, the default state is taken from the layout (
defaultVisible,defaultRequired,defaultReadOnly, visibility conditions, field-based color). - Rules with the
alwaystrigger are evaluated in list order (the number to the left of the name). Actions within a rule run from top to bottom. When multiple rules set the same property on the same target, the rule later in the list wins. - Hiding and locking on tabs and sections propagates to the fields inside (inheritance).
- In Display mode, all fields are locked and required flags are cleared.
- One-shot
onLoadrules run after the form loads, andonSaverules run on save. Their state changes (visibility, required, read-only) override the state from continuous rules, and a script viactxcan modify them afterward.
Rules only read fields used in their conditions and expressions. Typing into unrelated fields therefore does not unnecessarily re-evaluate rules.
Rule Editor
Open the designer and go to the Rules tab. The list is on the left, and the selected rule's detail is on the right.
- The list shows order, name, one-line summary, trigger, and Invalid, Disabled, and Inactive · limit badges. Rules can be searched by name or field. Click + New rule to add a rule with the "When value changes" trigger.
- The detail contains the name, trigger, WHEN block (conditions, "all match / any matches" selector), and THEN block (actions, executed in the listed order). A rule can be duplicated or deleted. Below the actions, the Affects in layout row lists its targets.
- Every edit is a single step in undo history (Ctrl+Z). Rapid typing in a single text box is coalesced into one undo step.
"Reads As" Sentence
Below the rule header, a natural-language sentence is generated, for example: "When value changes, if Status equals Approved, then lock Price". It helps verify that the rule does what you intend. The editor generates the sentence from the rule's settings and it cannot be edited directly. Its language matches the designer language.
Enabling and Disabling a Rule
The toggle next to a rule in the list sets enabled. A disabled rule (enabled: false) stays in the configuration but is not evaluated, making it ideal for temporarily turning a rule off. A missing value means enabled, so older configurations work unchanged.
Invalid Rules
If you delete a field, tab, or section referenced by a rule, the rule is not deleted. The designer records invalidReason with the list of missing targets and shows it with an Invalid badge and a red notice listing what is missing. At runtime, such a rule is skipped without causing an error.
- Fix it by selecting an existing field in the rule or re-adding the deleted field. The flag is recalculated on every edit and when loading the configuration.
- Invalid rules are excluded from inter-rule cycle detection.
Impact Dialog When Deleting
Before deleting a field, section, tab, or rule, the designer shows an impact dialog: how many fields will be removed, which rules will become invalid (kept, but not evaluated), and which scripts reference the removed fields (these are not updated automatically). Confirm with Delete or cancel. You can revert the change with Undo until you close the designer.
Rule Limit in the Free Edition
The Community (Free) edition allows up to 3 rules. When exceeded, the designer displays a yellow bar "running X of Y rules", marks rules over the limit with an Inactive · limit badge, locks their toggle, and adds a toolbar warning. Rules beyond the limit are still saved. A Pro license removes the limit; see Licensing.
Rule Triggers
The trigger (trigger) is selected in the rule header. If omitted, always is used.
Always (always)
Labeled "When value changes" in the editor. Default trigger. The rule is evaluated after the form loads and again whenever any field used in its conditions (or the form mode) changes. Ideal for live logic: showing fields based on status, locking, calculating values, or updating a banner.
- Supports
setVisible,setRequired,setReadOnly,setCollapsed,setValue,setExpression,setBannerIntent,setBannerTitle,setBannerContent,setColor, andcallFunction. - State is persistent only while conditions are true: as soon as conditions stop being met, the field reverts to its default state.
callFunctionruns only when conditions become true or values in conditions change (not on every re-render). Loop protection stops after 10 calls to the same function from the same rule.- A rule with no conditions does not run.
blockSaveis not valid here.
On Load (onLoad)
Labeled "On form load" in the editor. The rule runs once after the form loads (and again if the form mode or rule configuration changes). Ideal for initial state that the user can subsequently change: collapsing sections, prefilling a value, showing a welcome banner, or calling an initialization function.
- Without conditions, it always applies. Conditions read form values at load time.
- Values set by
setValueorsetExpressiondo not mark the form as dirty. On a new item, they are saved normally. - Changes to visibility, required state, and read-only apply as a one-time override; subsequent field edits do not recalculate them.
callFunctionruns in the initialization phase (see init vs. user phase).
A value set by an onLoad rule (setValue, setExpression) does not mark the form as dirty, so merely opening the form does not trigger an unsaved-changes prompt. In Edit mode, however, it is written to SharePoint on save if it differs from the stored value. It is saved only if the user saves the form; closing without saving changes nothing.
On Save (onSave)
Labeled "On form save" in the editor. The rule runs when Save is clicked, after field validation passes and before the onBeforeSave script. Ideal for cross-field checks that do not fit field-level validation, and for values stamped at save time (timestamp, user assignment).
- The only trigger that supports the blockSave action.
- Values from
setValueandsetExpressionare written to the form, marked as dirty, and saved even in Edit mode. TheonBeforeSavescript already sees them viactx.getValue. If saving is blocked (returnsfalseor a string) or submission fails, values are rolled back to their previous state and the form stays as the user edited it. - Without conditions, it always applies.
- If you switch a rule from
onSaveto another trigger,blockSaveis replaced with a show action.
Condition Operators
A condition has the form { "fieldInternalName", "operator", "value" }. The value property is unused for isEmpty and isNotEmpty. Complex field types are compared by their visible parts:
- Person: ID, display name, email, login name.
- Lookup: ID and text.
- Managed metadata: label and term ID.
- Hyperlink: URL and description.
- Multi-value fields: true if the comparison matches any value.
- Attachments: file count after subtracting deleted files and adding new ones.
Equals equals
True when the field value matches value. Strings are compared case-insensitively with leading/trailing whitespace trimmed; numbers numerically ("10" equals 10); yes/no as true/false. For multi-value and person fields, matching any value is sufficient. An empty field never equals any value; use isEmpty to test emptiness.
{ "fieldInternalName": "Status", "operator": "equals", "value": "Schváleno" }
Not Equals notEquals
Opposite of equals. An empty field does not equal the specified value, so the condition is true. For multi-value fields, true when no value matches.
{ "fieldInternalName": "Status", "operator": "notEquals", "value": "Koncept" }
Contains contains
True when the field's text contains the given substring (case-insensitive). For multi-value and person fields, true if any value contains the substring. An empty field does not satisfy the condition. For groups ($userGroups), it acts as a membership check.
{ "fieldInternalName": "Title", "operator": "contains", "value": "faktura" }
Does Not Contain notContains
Opposite of contains. An empty field satisfies the condition.
{ "fieldInternalName": "Title", "operator": "notContains", "value": "storno" }
Greater Than greaterThan
Compares numbers and dates. Numbers use a decimal point (3.14, negative -5); dates use YYYY-MM-DD or YYYY-MM-DDTHH:mm in local time. For repeating tables and multi-value fields, the item count is compared. If either side is neither a number nor a date (including an empty field), the condition is false.
{ "fieldInternalName": "Cena", "operator": "greaterThan", "value": 10000 }
Less Than lessThan
Same as greaterThan, in the opposite direction. An empty field does not satisfy the condition (it is not treated as zero).
{ "fieldInternalName": "Termin", "operator": "lessThan", "value": "2026-12-31" }
Is Empty isEmpty
True for null, empty or whitespace-only text, empty array, empty repeating table, unselected person, lookup, or term, and attachments with no files. Does not need value.
{ "fieldInternalName": "Poznamka", "operator": "isEmpty" }
Is Not Empty isNotEmpty
Opposite of isEmpty. Useful for "if X is filled in, show Y".
{ "fieldInternalName": "Schvalovatel", "operator": "isNotEmpty" }
Rule Actions
Each action has a target (targetFieldInternalName), type (action), and value (value). Actions execute in the order listed.
Show / Hide setVisible
true shows the target, false hides it. Target can be a field, banner, tab (tab:id), or section (section:id). A hidden field is not validated. Hiding a tab or section hides everything inside it (inheritance).
{ "targetFieldInternalName": "section:sec_schvaleni", "action": "setVisible", "value": false }
Set Required setRequired
true makes the field required, false makes it optional. Target is a field (not a tab or section). In Display mode, required state is always cleared. Requiredness is checked on save; hidden and locked fields do not report errors.
{ "targetFieldInternalName": "DuvodZamitnuti", "action": "setRequired", "value": true }
Set Read-Only setReadOnly
true locks the target, false unlocks it. Target can be a field, tab, or section; locking a container locks all fields inside it.
In Edit and New modes, a locked field remains fully readable: instead of looking like a grayed-out disabled input, it renders with a subtly distinct background and border and normal text color. Text, number, and multi-line text are read-only inputs (text can be selected and copied); other types (choice, date, Yes/No, person, lookup, taxonomy, rating, location, and calculated) display their value in a locked box. Screen readers announce the field as read-only. The value remains unchanged in the form, saves as-is, and locking alone does not mark the form as dirty.
{ "targetFieldInternalName": "tab:tab_cena", "action": "setReadOnly", "value": true }
Collapse / Expand Section setCollapsed
true collapses the section, false expands it. Target must be a section (section:id), and it takes effect on sections configured as collapsible. Users can still toggle it manually afterward. If validation fails, a section containing an error expands automatically.
{ "targetFieldInternalName": "section:sec_prilohy", "action": "setCollapsed", "value": true }
Set Value setValue
Writes a fixed value into a field. The value can be text, number, true/false, empty string (clears the field), an object for complex types, or the token @Me (current user) or @Today (today's date). Target is a field.
- Enforced value: in an
alwaysrule, the value is written whenever it differs from the current value. As a result, the user cannot overwrite it while the conditions remain true. Comparison treats empty values (null,"",[]) as equal, matches dates with their ISO strings, and matches people by ID (or login name, email). - Clearing:
value: ""clears the field. An unset result (undefined) leaves the field unchanged. - Does not mark as dirty: writing does not count as a user edit, though in Edit mode a field with an active enforced value is saved.
- Loop protection: if rules overwrite each other on the same field (A sets B, B sets A), writing stops after 10 writes to a field within 1 second and a console warning is logged. After one second, the rule works again. The designer also statically detects cycles between rules and rules whose condition reads a field they themselves set.
{ "targetFieldInternalName": "Zadavatel", "action": "setValue", "value": "@Me" }
Call Script Function callFunction
Runs a named function from form scripts. Target is always $script, and value is the function name (must exist in scripts.functions, otherwise configuration validation fails). The function receives the ctx object.
- With
always, the function is called when conditions become true or their values change, with loop protection (10 calls). WithonLoad, once after load; withonSave, beforeonBeforeSave. - If scripts are not allowed on the tenant, the call is skipped and the rule's other actions still execute. See Script Policy.
{ "targetFieldInternalName": "$script", "action": "callFunction", "value": "prepocitejDph" }
Set Expression setExpression
Computes a field value from a formula over other fields, such as [Cena] * [Kusy]. Syntax, functions, and behavior are on the Expressions & Formulas page. The expression @Me inserts the current user just like setValue. Write behavior matches setValue (enforced value, loop protection). An expression that cannot be parsed as a formula is treated as a text template. An invalid numeric result (division by zero) clears the field.
{ "targetFieldInternalName": "Celkem", "action": "setExpression", "value": "ROUND([Cena] * [Kusy] * 1.21, 2)" }
Block Save blockSave
Stops saving and displays a message. Usable only in rules with the onSave trigger. Target is either $form (form-level error) or a field (the message appears next to the field and the form scrolls to it, expanding the section and switching tabs if needed). Value is the error message text and must not be empty. Multiple blocking rules display all messages together in the top panel.
{
"id": "rule-kontrola-ceny",
"name": "Cena musí být kladná",
"trigger": "onSave",
"matchType": "all",
"conditions": [{ "fieldInternalName": "Cena", "operator": "lessThan", "value": 1 }],
"actions": [{ "targetFieldInternalName": "Cena", "action": "blockSave", "value": "Cena musí být větší než 0." }]
}
Show Notification showNotification
Shows a non-blocking notice above the form (a bar with a Got it button). Only for the always trigger. It fires when the rule conditions start to hold after a user change (not met → met), never on form load, and it does not repeat while the conditions keep holding. The value is the message ({Field} tokens), optionally title and severity (info, warning – default, error, success). The target is $form. Texts can be translated on the Translations tab.
{ "targetFieldInternalName": "$form", "action": "showNotification", "value": "Over 500,000 the CFO must approve.", "severity": "warning" }
Confirm Change with Revert confirmChange
When the conditions start to hold after a user change, a modal dialog opens with Continue and Undo change buttons (custom texts confirmLabel / cancelLabel, optional title). Continue keeps the change. Undo change (or closing the dialog) reverts the target field to its value before the change; the revert does not open the dialog again. The target is the field to revert (usually the condition field). Only for the always trigger, never on form load. Several dialogs are shown one after another.
{
"id": "rule-cancel",
"name": "Confirm cancellation",
"trigger": "always",
"matchType": "all",
"conditions": [{ "fieldInternalName": "Status", "operator": "equals", "value": "Cancelled" }],
"actions": [{ "targetFieldInternalName": "Status", "action": "confirmChange", "value": "Really cancel {Title}?", "cancelLabel": "Keep the previous status" }]
}
Change Banner Intent setBannerIntent
Switches the color and icon of a Banner widget. Value is info, warning, error, or success.
{ "targetFieldInternalName": "widget_banner_1", "action": "setBannerIntent", "value": "warning" }
Change Banner Title setBannerTitle
Replaces the banner title. The text may include tokens [Field] or {Field} (field value), @Me, and @Today. Plain text is substituted; nothing is ever evaluated as a formula.
{ "targetFieldInternalName": "widget_banner_1", "action": "setBannerTitle", "value": "Žádost {Title}" }
Change Banner Content setBannerContent
Replaces the banner body text, just like setBannerTitle with token support.
{ "targetFieldInternalName": "widget_banner_1", "action": "setBannerContent", "value": "Částka [Cena] Kč čeká na schválení od @Me." }
Set Tab or Section Color setColor
Recolors a tab (tab:id) or section (section:id). Value is a preset color key, a hex color #rrggbb, or none (no color). Cannot be applied to fields.
{ "targetFieldInternalName": "section:sec_stav", "action": "setColor", "value": "#d13438" }
Blocking Save and Lifecycle
When Save is clicked, steps execute in this order:
- Field validation (required, format). Errors appear next to fields.
onSaverules. If anyblockSaveapplies, saving stops and messages appear next to fields and in the top panel.- Writes from
setValueandsetExpressioninonSaverules, andcallFunctionfrom those rules. onBeforeSavescript: if it returns text orfalse, saving stops (see JavaScript Scripts).- Submission to SharePoint.
blockSave works even when scripts are disabled. For validation that must always apply, prefer it over onBeforeSave.
Debugging Rules
When a rule does not behave as expected, enable debug mode. Append ?fcdebug=1 to the form URL (applies only to this page load and does not change the saved configuration), or enable debugMode. In the browser console (F12), you will see logs prefixed with [FC debug]:
- the reason for each evaluation (form load, value change with changed field names, mode or rule change);
- for each rule, the result of every condition with actual and expected values, whether the rule matched, and which actions ran;
- skipped rules with the reason (disabled, invalid, different trigger, no conditions);
- application of enforced values and loop blocks;
onLoadandonSaveresults, script calls, expression errors, and the dirty source on fields.
[FC debug] output: expanded rule evaluation group with conditions and results (open the form with ?fcdebug=1)Common reasons a rule "does not work": the rule is disabled or invalid, the trigger is onLoad instead of always, the condition value has a different format than the field (for example, display name instead of ID), or another rule lower in the list overwrote the same property.