Live checks
Ask the server to check a field while someone edits a form, show the result, and drop answers that a newer edit has replaced.
A field with a .LiveValidate(...) rule in Go can be checked before anything is saved. The admin
does this for you; a custom form calls collectionLiveValidation or globalLiveValidation. Set up
the rule with Live server validation.
The examples use that guide’s products collection, whose sale price must be lower than its
regular price.
Check a field
Send the unsaved values the rule needs, and the fields to check:
import { createClient } from '~/generated/ridu.generated';
const ridu = createClient({ baseURL: 'http://localhost:8080' });
const { evaluations } = await ridu.collectionLiveValidation(
'products',
{
// Send the regular price too: the rule compares these values.
data: { price: 100, salePrice: 120 },
fields: ['salePrice']
// Add id: product.id when editing a saved product.
}
);
for (const evaluation of evaluations) {
for (const issue of evaluation.issues) {
console.info(issue.path, issue.message);
}
}This returns an issue on salePrice, because 120 isn’t lower than 100. With salePrice: 80, it
returns none.
| Send | What |
|---|---|
data |
the form’s unsaved values, including any other field the rule reads; it can be incomplete |
fields |
the paths to check, such as salePrice, seo.title or variants.0.salePrice |
id |
the document’s ID when editing a saved one; leave it out for a new document |
For a global, call globalLiveValidation('site-settings', { data, fields }) without an id. A
second argument takes one locale and a signal.
Read the result
Each evaluation has a path, a status and issues:
| Result | Show |
|---|---|
checked, with issues |
the issues, beside the field |
checked, no issues |
nothing. Saving can still fail on another rule. |
skipped |
nothing, and not a success: the check didn’t run, for example because a value had the wrong type |
Keep an evaluation’s target when one is present and match feedback to fields with it; it’s an
opaque token, not a path to parse. A live check never saves and never runs .Validate(...), so
handle validation errors from create or update as well.
Drop outdated answers
Someone typing can trigger checks faster than they return. Cancel the previous check when the input changes, and ignore its answer:
let controller: AbortController | undefined;
async function checkSalePrice(price: number, salePrice: number) {
controller?.abort();
const current = (controller = new AbortController());
clearIssues('salePrice');
try {
const { evaluations } = await ridu.collectionLiveValidation(
'products',
{ data: { price, salePrice }, fields: ['salePrice'] },
{ signal: current.signal }
);
if (current.signal.aborted) return;
for (const evaluation of evaluations) {
for (const issue of evaluation.issues)
showIssue(issue.path, issue.message);
}
} catch (error) {
// A cancelled check rejects with the browser's abort error.
if (!current.signal.aborted) throw error;
}
}Choose when to check, such as on blur or after a short pause in typing. Cancel too when the form closes or switches document or locale.