Page Validator
A validator adds behaviour to a form page: show and hide sections depending on answers, check fields against each other, set defaults. It is a small class next to your page - no React state, no event handlers on every field.
Wiring
import { EccPageWrapper } from "@/ecc/core/EccPageWrapper";
import { EccPageValidator } from "@/ecc/core/EccPageValidator";
class PurchaseStarterValidator extends EccPageValidator {
// ...
}
export default function PurchaseStarter() {
return (
<EccPageWrapper validatorClass={PurchaseStarterValidator}> {/* pass the class, not an instance */}
<PurchaseStarterContent />
</EccPageWrapper>
);
}
Lifecycle
| once after the page is shown | hide optional sections, set start state |
| every time the user leaves a field | show and hide sections, cross-field checks |
| when the page is left or the tab is closed | clean up (synchronous code only) |
Return super.onChange() at the end - it returns true when no error was set.
Tools inside the validator
| current value of the field with this |
| hides or shows a field, EccPanel or EccHideable with this |
| shows |
Give every field you want to read or change an id:
<EccDropDown id="purchase-request-type" fieldLabel="Request type" value="purchase.requestType" data={data} valueOut
options={types} keyAttribute="id" valueAttribute="label" editable mandatory />
<EccHideable id="div-hygiene">
<EccBoolean id="purchase-details-hygiene" value="purchase.hygiene" data={data} valueOut editable trueLabel="Hygiene approval required" />
</EccHideable>
Ecc components in this example: EccDropDown, EccBoolean - how to use them is described in UI Components.
Example: dynamic sections
class PurchaseStarterValidator extends EccPageValidator {
override onPageLoad(): void {
this.setHidden("div-hygiene", true); // optional sections start hidden
this.setHidden("div-software", true);
}
override onChange(): boolean {
const type = this.getById("purchase-request-type"); // key of the selected option
this.setHidden("div-hygiene", type !== "medical-devices");
this.setHidden("div-software", type !== "it-software");
// contact person panel only if it differs from the requester
const sameAsRequester = Boolean(this.getById("purchase-requester-is-contact"));
this.setHidden("purchase-contact", sameAsRequester);
return super.onChange();
}
}
Example: field checks
export class PurchaseTaskValidator extends EccPageValidator {
override onChange(): boolean {
const approved = this.getById("decision-approved") as boolean;
const comment = (this.getById("decisionComment") as string | undefined)?.trim() ?? "";
if (approved === false && comment.length < 10) {
this.setError("decisionComment", "Please explain the rejection (at least 10 characters).");
}
return super.onChange();
}
}
A validator can be shared by several task pages of the same process - keep it in src/apps/{processId}/tasks/.
Good to know
- Hidden fields keep their value and are still part of the output. Hide a section to simplify the form, not to drop data.
mandatoryon a field marks it with a red star and shows it as invalid while it is empty - no validator code needed.- Errors are recalculated on every change: set them again in each
onChange()run, they are cleared before. onPageDestroy()also runs when the browser tab is closed. Only synchronous code is reliable there; usenavigator.sendBeacon()for a last HTTP call.
On this page
- Page Validator