Create custom validation rules for form components
Create custom validation rules for form components with sync and async validators
Component Validation
Creating Custom Validation
Custom validation allows you to create your own validation rules for form components. This is useful when standard validation rules don't meet your requirements.
1. Validator Structure
A custom validator could be asynchronous and should return ValidationResultI that corresponds next structure:
interface ValidationResultI {
isValid: boolean; // Whether validation passed
errorKey?: string; // Error key that will be used for i18n (if isValid === false)
}
type ValidatorFunction = (value: string) => ValidationResultI | (value: string) => Promise<ValidationResultI>;2. Custom Validator Example
Let's create a custom email input field. Here are the steps that should be done:
2.1 Creating Validators
Example of an email format validator:
// src/components/MyComponent/validators/emailValidator.js
export const email = () => (value) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const isValid = emailRegex.test(value);
return {
isValid,
errorKey: isValid ? null : "EMAIL_INVALID",
};
};Example of an email existence validator:
// src/components/MyComponent/validators/emailExistsValidator.js
export const emailExists = () => async (value) => {
try {
const url = "https://example.org/emails/exists";
const response = await fetch(`${url}?email=${value}`);
const isValid = !response.ok;
return {
isValid,
errorKey: isValid ? null : "EMAIL_ALREADY_EXISTS",
};
} catch {
return {
isValid: false,
errorKey: "EMAIL_ALREADY_EXISTS",
};
}
};2.2 Creating Control
WcControlledElement provides logic for adding validation to the component. To use it, call createControlWithValidation during connectedCallback phase, it accepts next arguments:
| Parameter | Type | Default Value | Description |
|---|---|---|---|
| validators | ValidatorFunction[] | [] | Array of validators |
| options | CreateControlWithValidationOptionsI | Configuration options |
CreateControlWithValidationOptionsI has next structure:
| Field Name | Type | Default Value | Description |
|---|---|---|---|
| element | HTMLElement | rootEl.querySelector('input') | HTML element for validation |
| tooltipElement | HTMLElement | rootEl.querySelector('.input-tooltip') | Element for displaying tooltips |
| validCallback | () => void | () => | Callback for successful validation |
| invalidCallback | () => void | () => | Callback for failed validation |
| pendingCallback | () => void | () => | Callback during validation |
| elementToListen | HTMLElement | Value of element field | Element for event listening |
| validationMap | Record<string, ValidatorFunction> | Map of validators |
Usage example:
// src/components/MyEmailInputComponent/MyEmailInputComponent.js
import manifest from "./MyEmailInputComponentManifest.manifest";
import WcControlledElement from "@claspo/components/WcControlledElement";
import { emailExists } from "./validators/emailExistsValidator";
import { email } from "./validators/emailValidator";
export default class MyEmailInputComponent extends WcControlledElement {
static define = {
name: "my-email-input",
model: manifest.name,
manifest: manifest,
};
manifest = manifest;
connectedCallback() {
// Validators provided via this map could be enabled/disabled from props
const validationMap = {
EMAIL_EXISTS: emailExists(),
};
this.control = this.createControlWithValidation([email()], {
validationMap,
});
}
}2.3 Adding Error Translations
Add validation error translations to the component's manifest. Translation keys are formed using the pattern:
control,validation,validationErrors,${VALIDATOR_ERROR_KEY}
// src/components/MyEmailInputComponent/MyEmailInputComponent.manifest.js
const manifest = {
//...
i18n: {
en: {
//...
+ "control,validation,validationErrors,EMAIL_EXISTS": "Email already exists",
+ "control,validation,validationErrors,EMAIL_INVALID": "Email format is invalid",
},
ua: {
//...
+ "control,validation,validationErrors,EMAIL_EXISTS": "Ця ел. пошта вже існує",
+ "control,validation,validationErrors,EMAIL_INVALID": "Невірний формат ел. пошти",
},
//...repeat for rest languages
},
//...
};2.4 Configuring Validation via Props
Validation can be configured through ContactMappingOptionI or directly via component props:
// src/components/MyEmailInputComponent/MyEmailInputComponent.manifest.js
const manifest = {
// ...
defaultProps: {
control: {
+ validation: {
+ required: true,
+ validator: "EMAIL_EXISTS",
+ },
},
},
};
export default manifest;Note: Each component has a built-in
requiredvalidator, so there is no needed to implement it manually.
Updated 1 day ago
