API
This section documents the complete fonk API. Keep in mind that fonk is only concerned with managing validations in Vanilla JavaScript.
In a real app, you'll also want to use some integration library like react-final-form.
Validation Schema definition
ValidationSchema
In this structure you can define all the validations associated to a given form (field and record validations).
This allow us to define all validation associated to a given form in a declarative way.
Properties:
field: optional entry, here you can define all field validations associated to a given form (see FieldValidationSchema for more information).
record: optional entry, here you can define all record validations associated to a given form (see RecordValidationSchema for more information).
export interface ValidationSchema {field?: FieldValidationSchema;record?: RecordValidationSchema;}
FieldValidationSchema
In this structure you can define all field validations associated to a given form. For each field, it has to add a validator list. Each validator could be a field sync validator, field async validator or full field validation
Properties:
- field name: Field name which it wants to apply the validator
Values:
- An array of field sync validator, field async validator or full field validation
const validationSchema: ValidationSchema = {field: {myFieldName: [Validators.required, // This is a sync validatorloginValidator, // This is a custom async validator{validator: Validators.required, // This is a sync validatorcustomArgs: { otherField: 'other' },message: 'Required field',},{validator: loginValidator, // This is a custom async validatorcustomArgs: { otherField: 'other' },message: 'Invalid login',},],},};
FullFieldValidation
Structure to define a field validation:
Properties:
- validator: field async validator or field sync validator validation function to apply. As syntactic sugar, you could provide an object with
validator
property. - customArgs: optional, here you can pass any additional configuration, needed to setup the validator (e.g. in a max-length validation the length value, or in a regEx validator the regEx pattern).
- message: optional, in this parameter you can override the default message(s) that the validator generates.
Examples:
You can find this example in javascript example and typescript example.
Schema Field validations
Let's say we want to build a Login Form, and it contains the following record:
const loginModel = {user: '',password: '',};
We want to validate that both user and password are required field, a validation schema to define these validations:
import { Validators } from '@lemoncode/fonk';const loginFormValidationSchema = {field: {user: [Validators.required],password: [Validators.required],},};
Let's follow up completing this form validation, in this case it wants to ensure that the user field is required and a well formed email address:
import { Validators } from '@lemoncode/fonk';const loginFormValidationSchema = {field: {user: [Validators.required, Validators.email],password: [Validators.required],},};
Let's add one more step of complexity in this case it wants to ensure that the password field name is at least 5 characters length, it can use the min-length validator, but it has to feed and additional parameter to indicate the minumum length, in this case the validation schema accepts both function and structure based definition to include validation it will use the second option.
import { Validators } from '@lemoncode/fonk';const loginFormValidationSchema = {field: {user: [Validators.required, Validators.email],password: [Validators.required,{validator: Validators.minLength,customArgs: { length: 3 },},],},};
RecordValidationSchema
In this structure you can define all record validations associated to a given form. For each record, it has to add a validator list. Each validator could be a record sync validator, record async validator or full record validation
Properties:
- record name: Record name which it wants to apply the validator
Values:
- An array of record sync validator, record async validator or full record validation
const validationSchema: ValidationSchema = {record: {myRecordName: [freeShippingAllowed, // This is a custom sync validatorasyncFreeShippingAllowed, // This is a custom async validator{validator: freeShippingAllowed, // This is a sync validatormessage: 'Total must be greater than 30USD',},{validator: asyncFreeShippingAllowed, // This is a custom async validatormessage: 'Total must be greater than 60USD',},],},};
FullRecordValidation
Structure to define a record validation:
Properties:
- validator: record async validator or full record validation validation function to apply.
- message: optional, in this parameter you can override the default message(s) that the validator generates.
Examples:
You can find this example in javascript example and typescript example.
Record Field validations
Sometimes you need to create global validation that is not tied up to a specific field, or you want it to be fired once the user has fullfilled all the data in the validation form, a use case for this type of validation could be: shopping cart checkout, offer free shipping if total amount (including discount) is greater than 30 USD
const checkoutForm = {subtotal: 0,discount: 0,};
Let's define our record validator rule:
const freeShippingAllowed = ({ values }) => {const succeeded = values.subtotal - values.discount >= 30;return {type: 'RECORD_FREE_SHIPPING',succeeded,message: succeeded? '': 'Total must be greater than 30USD to get cost free shippings',};};
const validationSchema = {record: {freeShippingValidation: [freeShippingAllowed],},};
createFormValidation
Factory method creates a new FormValidation. This is the main entry point when creating FormValidations
Arguments:
- ValidationSchema: validations associated to a given form (field and record validations) ValidationSchema
Returned Value
- FormValidation: a FormValidation instance to fire validations. See FormValidation for more information.
const validationSchema: ValidationSchema = {// Your validation schema};const formValidation: FormValidation = createFormValidation(validationSchema);
FormValidation
This is the main class you will interact with when validating forms, it allows you to inform the form validation schema in the constructor of the class, then it exposes methods to fire validateField, validateRecord and validateForm (fire all field plus record validations).
Constructor
In order to instantiate the class it needs to inform a ValidationSchema, internally the constructor will traverse the validation schema and categorize field and record validations.
Arguments:
- validatonSchema: The form ValidationSchema
constructor(validationSchema: ValidationSchema) {
ValidateField
Allows us to fire all the validations associated to given field, this method is async and it returns a promise with a validation result.
How does it works:
- It starts iterating over all the associated fields that have validations defined in the ValidationSchema:
- The validation engine will start sequentially firing the list of validations associated to that field in the form validation schema.
- It will stop iterating through all validations associated to the given field: A. When it finds a validation that fails, in that case it will indicate that the field validation failed, which validation failed, plus the error message associated. B. When all associated fields validations succeeded, in that case it will return a succeeded validation result.
Arguments:
- fieldId: name of the field to be validated (e.g. run all the validation associated to the form password field).
- value: current value of the field.
- values: optional argument. All form values (e.g. in a login form, values would be username and password fields).
Returns:
- Promise<ValidationResult>: Result of firing all the field validations.
public validateField(fieldId: string, value: any, values?: any): Promise<ValidationResult>
ValidateRecord
Allows us to fire all record validations associated to the form, this method is async returns a promise with a RecordValidation result.
How does it works:
- It passes as arguments the whole form information (aka. record or values).
- The validation engine will start sequentially firing the list record validations associated to the form.
- For each record, it will fire related validations and stop it: A. When it finds a validation that fails, in that case it will indicate that the record validation failed, which validation failed, plus the error message associated. B. When all associated record validations succeed, in that case it will return a validation succeed result.
Arguments:
- values: All form values (e.g. in a login form, values would be username and password fields).
Returns:
- Promise<RecordValidationResult>: Result of firing all the record validations.
public validateRecord(values?: any): Promise<RecordValidationResult>
ValidateForm
Fires all fields and record validations in one go, how does it work:
- Starts iterating over all the associated fields that have validations defined in the ValidationSchema:
- The validation engine will start sequentially firing the list of validations associated to each field in the form validation schema.
- It will stop iterating through all validations associated to each field as same way as validateField.
- Then, it starts iterating sequentially firing the list of validations associated to each record and it will stop as same way as validateRecord.
- Once the engine it's done with all fields and records validations it returns the whole result, grouped in two areas:
- An Object containing two keys:
- 'fieldErrors': contains an object fieldId/ValidationResult.
- 'recordErrors': contains an object with recordId/ValidationResult.
- An Object containing two keys:
Arguments:
- values: all form values (e.g. in a login form, values would be username and password fields).
Returns:
- Promise<FormValidationResult>: Result of firing all the field and record validation results.
validateForm(values: any): Promise<FormValidationResult>
Validaton Result structures
ValidationResult
A field or record validation function will return a ValidationResult
Properties
- type: Validator applied (e.g. required, email, min-length...).
- succeeded: Whether if the validation succeeded (true) or failed (false).
- message: Error message. Empty if all the validations evaluated succeeded.
export interface ValidationResult {type: string;succeeded: boolean;message: string | string[];}
RecordValidationResult
Whenever we validate all form record entries (ValidateRecord), a RecordValidationResult is returned.
- succeeded: Whether if the record validations succeeded (true) or failed (false).
- recordErrors: collection of validation results grouped by recordId.
export interface RecordValidationResult {succeeded: boolean;recordErrors: { [recordId: string]: ValidationResult };}
FormValidationResult
Whenever it validates a form with ValidateForm (trigger all field and record validations associated to that form) it will return a FormValidationResult.
export interface FormValidationResult {succeeded: boolean;fieldErrors: { [fieldId: string]: ValidationResult };recordErrors: { [recordId: string]: ValidationResult };}
Properties:
- succeeded: Whether if all validations succeeded (true) or any of them failed (false).
- fieldErrors: Collection of field ValidationResults grouped by fieldId.
- recordErrors: Collections of record ValidationResults grouped by recordId.
Validators
FieldValidation function type
FieldValidation function type is the one used to define field validator functions (for instance a function that validates if a field has been informed, or if it is a valid email). FieldValidation apply to a single field although is possible that a field validation could read values from another form field (for instance the field PartnerId is required only if the isPartner boolean value is true),
Field validator functions must comply with a given signature, in this case, it accepts two signatures, sync and async.
Field Synchronous Validator
Synchronous validator function.
Arguments
- FieldValidatorArgs: It passes here information like id of the field to validate, actual value, values and customArgs. See FieldValidatorArgs for more information.
Returned Value
- ValidationResult: Whether if field validations applied to the selected field succeeded or not (in case not, additional information to be provided like id of the validator that failed plus error message).
export type FieldValidationFunctionSync = (fieldValidatorArgs: FieldValidatorArgs) => ValidationResult;
Field Asynchronous Validator
Asynchronous validator function.
Arguments
- FieldValidatorArgs: It passes here information like id of the field to validate, actual value, values and customArgs. See FieldValidatorArgs for more information.
Returned Value
- Promise<ValidationResult>: Async promise. Once promise is resolved, it returns whether if field validations applied to the selected field succeeded or not (in case not, additional information to be provided like id of the validator that failed plus error message).
export type FieldValidationFunctionAsync = (fieldValidatorArgs: FieldValidatorArgs) => Promise<ValidationResult>;
FieldValidationArgs
FieldValidation functions accept as input parameter a FieldValidationArgs, the fonk engine will feed the needed properties to the validator when a field validation is fired.
Properties:
- value: current value of the field to be evaluated.
- values: whole form values (all fields associated to the form).
- customArgs: if it need to pass any configuration parameter to the validator (for instance, in a min-length validation the numeric value, or in a password matches another field the id of the field to compare against).
- message: you can override the default error(s) message generated by the validators and set your own (for instance in a regEx / pattern validation you may want to customize the error message for a credit card field to something like this is not a valid credit card number instead of the generic Pattern does not match).
export interface FieldValidatorArgs {value: any;values?: any;customArgs?: any;message?: string | string[];}
RecordValidation function type
RecordValidation function type is the one used to define record validator functions. What is a record validator function? These validations are associated to the whole form instead of a single field, for instance: if the total amount of your shopping cart is more than 50 USD then you get free shipping, if not warn the user.
Field validator functions must comply with a given signature, in this case, it accepts two signatures, sync and async.
Record Synchronous Validator
Synchronous validator function.
Arguments
- RecordValidatorArgs: It passes here information like values and message. See RecordValidatorArgs for more information.
Returned Value
- ValidationResult: Whether if field validations applied to the selected field succeeded or not (in case not, additional information to be provided like id of the validator that failed plus error message).
export type RecordValidationFunctionSync = (recordValidatorArgs: RecordValidatorArgs) => ValidationResult;
Record Asynchronous Validator
Asynchronous validator function.
Arguments
- RecordValidatorArgs: It passes here information like values and message. See RecordValidatorArgs for more information.
Returned Value
- Promise<ValidationResult>: Async promise. Once promise is resolved, it returns whether if field validations applied to the selected field succeeded or not (in case not, additional information to be provided like id of the validator that failed plus error message).
export type RecordValidationFunctionAsync = (recordValidatorArgs: RecordValidatorArgs) => Promise<ValidationResult>;
RecordValidationArgs
RecordValidation functions accept as input parameter a RecordValidationArgs, the fonk engine will feed the needed properties to the validator when a record validation is fired.
Properties:
- values: whole form values (all fields associated to the form).
- message: you can override the default error(s) message generated by the record validators and set your own.
export interface RecordValidatorArgs {values: any;message?: string | string[];}
Built in validators
required
Succeeds if a field value is informed, fails if the field is not informed (null, undefined, or empty string).
Accepts a custom paramater to instruct the validator to trim the incoming values (if true a value like ' ' would be treated as an empty string).
export interface RequiredArgs {trim: boolean; // Default value equals true}export const required: FieldValidationFunctionSync<RequiredArgs> = (fieldValidatorArgs) : ValidationResult => {...}
Usage:
- Simple, (trim default value equals true):
import { Validators, createFormValidation } from '@lemoncode/fonk';const validationSchema = {field: {login: [Validators.required],},};
customArgs
import { Validators, createFormValidation } from '@lemoncode/fonk';const validationSchema = {field: {login: [Validators.required],password: [{validator: Validators.required,customArgs: { trim: false },},],},};
Example:
You can find this example in javascript example and typescript example.
Succeeds if a field value is a well formed email, fails if not.
If the string is empty it won't fail (to cover this case use the required validator).
export const email: FieldValidationFunctionSync = (fieldValidatorArgs) : ValidationResult => {...}
Usage:
import { Validators } from '@lemoncode/fonk';const validationSchema = {field: {email: [Validators.email],},};
Example:
You can find this example in javascript example and typescript example.
pattern
Succeeds if a field matches with a define regex, fails if not. This regular expression can be either a RegExp instance or a string.
If the string is empty it won't fail (to cover this case use the required validator).
Is mandatory to pass the regEx expression to be evaluated.
export interface PatternArgs {pattern: string | RegExp;}export const pattern: FieldValidationFunctionSync<PatternArgs> = (fieldValidatorArgs) : ValidationResult => {...}
Usage:
String:
import { Validators } from '@lemoncode/fonk';const validationSchema = {field: {phone: [{validator: Validators.pattern,customArgs: { pattern: '^(7|8|9)\\d{9}$' },},],},};
Regex:
import { Validators } from '@lemoncode/fonk';const validationSchema = {field: {phone: [{validator: Validators.pattern,customArgs: { pattern: /^(7|8|9)\d{9}$/ },},],},};
Regex constructor:
import { Validators } from '@lemoncode/fonk';const validationSchema = {field: {phone: [{validator: Validators.pattern,customArgs: { pattern: new RegExp(/^(7|8|9)\d{9}$/) },},],},};
Example:
You can find this example in javascript example and typescript example.
min-length
Succeeds if a field length is greater than the one informed in the customArgs.length
If the string is empty it won't fail (to cover this case use the required validator).
Is mandatory to pass the min length value.
export interface LengthArgs {length: number;}export const minLength: FieldValidationFunctionSync<LengthArgs> = (fieldValidatorArgs) : ValidationResult => {...}
Sample usage:
import { Validators } from '@lemoncode/fonk';const validationSchema = {field: {description: [{validator: Validators.minLength,customArgs: { length: 10 }, // Valid description for length greater than 10 chars},],},};
Example:
You can find this example in javascript example and typescript example.
max-length
Succeeds if a field length is less than the one informed in the customArgs.length
If the string is empty it won't fail (to cover this case use the required validator).
Is mandatory to pass the max length value.
export interface LengthArgs {length: number;}export const maxLength: FieldValidationFunctionSync<LengthArgs> = (fieldValidatorArgs) : ValidationResult => {...}
Sample usage:
import { Validators } from '@lemoncode/fonk';const validationSchema = {field: {description: [{validator: Validators.maxLength,customArgs: { length: 20 }, // Valid description for length lower than 20 chars},],},};
Example:
You can find this example in javascript example and typescript example.
array-validator
Validates an array form field, and returns an array of validation results per row/field.
Is mandatory to feed the validation schema.
export interface ArrayArgs {field: FieldValidationSchema;}export const validator: FieldValidationFunctionAsync = validatorArgs => {
Sample usage:
const validationSchema = {field: {products: [{validator: Validators.array,customArgs: {field: {name: [Validators.required],quantity: [Validators.required, isNumber],price: [Validators.required, isNumber],},},},],},};
Example:
You can find this example in javascript example.
Third party validators:
Prior to create a custom validator, check out if there is already one implemented that covers the functionality you need.
You can find a list of validators in third party validators.
Custom validators
A custom validator is a function used for validate a field or record.
It could use Field Synchronous Validator or Field Asynchronous Validator for fields and Record Synchronous Validator or Record Asynchronous Validator for records.
You could see some examples creating custom validators in:
Sync custom validators
Async custom validators