Validators
Adding validators to your Control Fields
Section titled “Adding validators to your Control Fields”Validators provide contextual messages for errors in Control Fields.
A Validator can validate different types of data, and each Validator will have a set of validations. For example, a String Validator will be able to check the length of a string, meanwhile a Number Validator can check the maximum or minimum value. You can also create custom Validators, please check the section Creating a custom Validator to know more.
Let’s create a password input with a required Validator. Just add a validator property to a Control Field as shown below:
{ "form": [ { "uid": "userPasswordInput", "kind": "control", "widget": "textinput", "path": "user.password", "validator": { "type": "string", "required": true } } ]}You can add more validators, triggering multiple errors if one or more of the requirements are not fulfilled. Let’s add validations for minimum length 8 characters, maximum length 20 characters and a pattern to check that the password has only letters and numbers.
{ "form": [ { "uid": "userPasswordInput", "kind": "control", "widget": "textinput", "path": "user.password", "validator": { "type": "string", "required": true, "minLength": 8, "maxLength": 20, "pattern": "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]+$" } } ]}Let’s give it a try!
Custom error messages
Section titled “Custom error messages”By default, validators use Zod’s built-in error messages. You can override these by providing a messages property with custom error messages for each validation rule.
The messages property accepts a Record<string, Localizable> where each key corresponds to a validation rule and the value is either a plain string or a translation config object for i18n support.
Plain string messages
Section titled “Plain string messages”{ "validator": { "type": "string", "required": true, "minLength": 8, "messages": { "required": "Please enter your password", "minLength": "Password must be at least 8 characters" } }}Translation config messages (i18n)
Section titled “Translation config messages (i18n)”{ "validator": { "type": "string", "required": true, "messages": { "required": { "key": "errors.password.required", "default": "Please enter your password" } } }}Here’s a more complete example with custom messages for different validator types:
Validator types reference
Section titled “Validator types reference”Each validator type supports a specific set of validation rules. Below are the available message keys for each type.
String validator
Section titled “String validator”| Property | Message key | Description |
|---|---|---|
| (type check) | invalid | Value is not a string |
required | required | Empty string when required: true |
minLength | minLength | String length is below the minimum |
maxLength | maxLength | String length exceeds the maximum |
pattern | pattern | String does not match the regex pattern |
format | format | String does not match the format (email, url, uuid, hostname, ipv4, ipv6, date, time, date-time, duration) |
enum | enum | Value is not one of the allowed values |
const | const | Value does not match the exact value |
Number validator
Section titled “Number validator”| Property | Message key | Description |
|---|---|---|
| (type check) | invalid | Value is not a number |
required | required | Empty string when required: true |
minimum | minimum | Value is below the minimum |
maximum | maximum | Value exceeds the maximum |
exclusiveMinimum | exclusiveMinimum | Value is not greater than the exclusive minimum |
exclusiveMaximum | exclusiveMaximum | Value is not less than the exclusive maximum |
multipleOf | multipleOf | Value is not a multiple of the specified number |
enum | enum | Value is not one of the allowed values |
const | const | Value does not match the exact value |
Boolean validator
Section titled “Boolean validator”| Property | Message key | Description |
|---|---|---|
| (type check) | invalid | Value is not a boolean |
required | required | Empty string when required: true |
const | const | Value does not match the expected boolean value |
Array validator
Section titled “Array validator”| Property | Message key | Description |
|---|---|---|
| (type check) | invalid | Value is not an array |
required | required | Array is empty when required: true |
minItems | minItems | Array has fewer items than the minimum |
maxItems | maxItems | Array has more items than the maximum |
Creating a custom validator
Section titled “Creating a custom validator”To create custom validators, implement functions that follow the CustomValidatorSchemaFn interface. For example, let’s create a validator that allows us to enter only certain names:
export const allowedNames: CustomValidatorSchemaFn = (names: string[]) => z.string().check( z.superRefine((val, ctx) => { if (val && names.includes(val) === false) { ctx.addIssue({ code: 'custom', message: `Name "${val}" not in ${names.map((name) => `"${name}"`).join(', ')}`, input: val, }); } }), );Next, inform the form that it should use the custom validator when it encounters a specific key in the validator declaration within your JSON. To do this, create a CustomValidatorSchemas object and pass it to the form through its customValidators input.
import * as Core from '@golemui/core';import { allowedNames } from './custom-validators/allowed-names';
const customValidators: Core.CustomValidatorSchemas = { allowedNames,};
export function FormPage() { return ( <div> <React.FormComponent (...) customValidators={customValidators} /> </div> );}import * as Core from '@golemui/core';import { allowedNames } from './custom-validators/allowed-names';
@Component({ selector: 'my-form-app', template: `<gui-form (...) [customValidators]="customValidators"> </gui-form> `,})class MyFormApp { protected customValidators: Core.CustomValidatorSchemas = { allowedNames, };}import * as Core from '@golemui/core';import { allowedNames } from './custom-validators/allowed-names';
@customElement('lit-form')export class FormElement extends LitElement { protected customValidators: Core.CustomValidatorSchemas = { allowedNames, };
render() { return html` <gui-form (...) .customValidators=${this.customValidators} ></gui-form> `; }}Finally, declare your validator:
{ { kind: 'input', widget: 'textinput', path: 'user.name', validator: { type: 'custom', allowedNames: ['John', 'Jane'] } },}Type something different from John and Jane to trigger the validation error.
Configuring when validation triggers
Section titled “Configuring when validation triggers”To allow users to define when field validation should run, set the validateOn: ValidateOn property at the form level.
type ValidateOn = | 'eager' | 'change' | 'blur' | 'submit' | ('change' | 'blur' | 'submit')[];When not set, the default validateOn behaviour is 'eager'.
ValidateOn behaviour
Section titled “ValidateOn behaviour”'change': When the user interacts with the field and changes its value.'blur': When the user has interacted with the field and leaves the field.'submit': When using ‘submit’, validation triggers when the ‘submit’ event is emitted. When that happens, all fields are also touched first.
{ widget: 'button', label: 'Create User', on: { click: 'submit', },}'eager': Validates when any of the above happens.
import * as Core from '@golemui/core';
export function FormPage() { return ( <div> <React.FormComponent (...) validateOn="change" /> </div> );}import * as Core from '@golemui/core';
@Component({ selector: 'my-form-app', template: `<gui-form (...) [validateOn]="validateOn"> </gui-form> `,})class MyFormApp { protected validateOn: Core.ValidateOn = 'change';}import * as Core from '@golemui/core';
@customElement('lit-form')export class FormElement extends LitElement { protected validateOn: Core.ValidateOn = 'change';
render() { return html` <gui-form (...) .validateOn=${this.validateOn} ></gui-form> `; }}