Validation, schema, expression, and author-defined
Three layers of field validation, when each runs, and how errors surface in the UI.
Validation in SharePoint Forms365 runs at three layers, in order:
1. Schema validation (declarative)
Built into every field type. No code:
| Property | Description |
|---|---|
requiredboolean | Field must have a value. |
requiredIfexpression | Required only when the expression returns true. See the requiredIf reference. |
minLength / maxLengthnumber | Text-length bounds. |
min / maxnumber | date | Numeric / date bounds. |
patternregex | Text must match the regular expression. |
2. Expression validation
The field's Custom validation rule (assertExpression) runs an
expression at save time. The field is
valid only while that expression is true, and Custom validation message (
assertMessage) is what the user sees when it is not. Inside this rule, and only here,
$value means the field's own value:
On the End date field: never before Start
$value >= {StartDate}
On a consent checkbox: must be ticked
$value == true
3. Author validation (JavaScript)
The most expressive layer. Per-field onValidate handlers receive the
current value and return either nothing (valid) or a string (invalid, the string
becomes the error message):
Custom email-domain validation
f365.field('ContactEmail').on('validate', (value) => {
const domain = (value ?? '').split('@')[1]?.toLowerCase();
if (!domain?.endsWith('.gov.au')) return 'Must be a .gov.au email address.';
});
Async validation against an external API
f365.field('Sku').on('validate', async (value) => {
if (!value) return;
const exists = await f365.http.get<{ active: boolean }>(`/api/sku/${value}`);
if (!exists?.active) return 'SKU not found or inactive.';
});
Form-level onValidate runs after every field-level handler and gets
the whole form payload, useful for cross-field rules.
When validation runs
| Property | Description |
|---|---|
On blur | Field-level validation runs when the user leaves the field. Provides immediate feedback without being annoying. |
On change (debounced) | Some types (e.g. patterns on number fields) re-validate after a 300ms debounce while typing. |
On submit | Every layer runs in order. The first failure focuses the bad field. |
How errors render
Errors surface via the Fluent v9 Field's validationState
slot, never as custom red-text markup. This means screen readers correctly
announce the error via aria-describedby, and the visual treatment is
consistent across every field type.
Related
Related articles
- requiredIf, conditional required
Mark a field required only when another field has a specific value.
- Save flow, what happens when the user clicks Submit
The two-phase save pipeline, validation, primary write, then post-save writers for attachments, signatures, images, and child rows.
- f365.events, form-level event bus
Subscribe to form lifecycle events, onLoad, onChange, onBeforeSave, onSave, onSaveError, onValidate, onCancel, onModeChange, onPageChange.