Skip to content

Validators

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!

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>
);
}

Finally, declare your validator:

{
{
kind: 'control',
widget: 'textinput',
path: 'user.name',
validator: { type: 'custom', allowedNames: ['John', 'Jane'] }
},
}

Type something different from John and Jane to trigger the validation error.

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'.

  • '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>
);
}