Adding custom validators
Naturally, it is necessary to add custom validation rules.
IMPORTANT: keep in mind that the validation rules built in the frontend will not be used in backend (if not implemented there as well).
Every custom validation rule config must be defined in validators
array in root plugin registration object.
window.registerKaskoPlugin('kasko-plugin', (kasko) => {
return {
+ validators: [...],
};
});
It can contain multiple validation rules, but none of the same name
. Framework will throw error if already existing validation rule with same name
is present.
Every validation rule must have name
property and validate
method.
{
name: 'rule_name',
validate: () => null,
}
name: string
name: string
Name as unique string
that will be used in field definition (i.e only_emoji_chars_allowed
).
validate: (context: PluginValidationContext) => (null | Record<string, boolean>)
validate: (context: PluginValidationContext) => (null | Record<string, boolean>)
Validation function that has one argument and returns either null
or object
with validation rule names that contains errors (e.g. { at_least_n_chars_present_in: true }
means current field will have error at_least_n_chars_present_in
and null
means no error).
PluginValidationContext {
fieldName: string;
value: string | undefined;
args: string[];
disabled: boolean;
}
Note that PluginValidationContext
doesn't return any other form values.
If there's a need to access input state or form state inside validator (e.g. to validate current field based on other fields/input value), then you can expose kasko
service to validator function and access state or form values using available methods: getState
or getFormState
.
{
name: 'rule_name',
- validate: customValidation,
+ validate: customValidation(kasko),
}
- const customValidation = ({ value }) => {
+ const customValidation = (kasko) => ({ value }) => {
+ const formState = kasko.getFormState();
...
}
Example validators
Simple usage
Simple validator that will show error on current input if emoji.
NOTE: Remember to respect required
validator - it's ok to allow empty string in this example, because field with this validation rule might not be required
.
In this example "a" and "a😀" will fail, but "" and "😀😁" will pass this validation rule.
const ALL_EMOJI = /^[\uD800-\uDBFF\uDC00-\uDFFF]*$/;
window.registerKaskoPlugin('kasko-plugin', (kasko) => {
return {
validators: [
// Adds validation rule `only_emoji_chars_allowed`
{
name: 'only_emoji_chars_allowed',
validate(context) {
// Show no error if field is not set
if (!context.value) {
return null;
}
// Detects if current input value contains only emoji chars
const allCharsAreEmoji = ALL_EMOJI.test(context.value);
if (!allCharsAreEmoji) {
// Sets error to current input field
return {
only_emoji_chars_allowed: true,
};
}
// Clears error for current input
return null;
},
},
],
};
});
Complex usage
This is a more complex validator that takes in 2 arguments, one of them is a number and second is another field name. Then we check that field names value and detect if current input contains n
number of chars that are in other field.
Valid case for this rule would be:
Validation definition: "at_least_n_chars_present_in:3,control_field"
Current field value: "ace"
Form value:
{ control_field: 'abcde' }
window.registerKaskoPlugin('kasko-plugin', (kasko) => {
return {
validators: [
/**
* Adds validation rule `at_least_n_chars_present_in`
*
* @example usage in field definition:
* `at_least_n_chars_present_in:3,control_field`
*
* It has 2 arguments `3` and `control_field`
*/
{
name: 'at_least_n_chars_present_in',
validate(context) {
// Show no error if field is not set
if (!context.value) {
return null;
}
// Accessing arguments from validation definition
const [minChars, otherFieldName] = context.args;
// Getting value for other field (note that other field might not be inside
// current form, so we need to also check input state)
const otherFieldValue = kasko.getFormState(otherFieldName) || kasko.getState(`input.${otherFieldName}`);
// Creates a regexp for getting `n` chars from other field value
const containsChars = new RegExp(`^[${otherFieldValue}]*$`).test(context.value);
const hasMinChars = context.value.length >= parseInt(minChars, 10);
// Checks with current input value
if (!(containsChars && hasMinChars)) {
// Sets error to current input field
return {
at_least_n_chars_present_in: true,
};
}
// Clears error for current input
return null;
},
},
],
};
});
Last updated