Fonk Doc
1. General
2. Validators
3. Messages
4. Form Libraries
5. API
APIValidation Schema definitioncreateFormValidationValidaton Result structuresValidators
6. Posts

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:

const validationSchema: ValidationSchema = {
field: {
myFieldName: [
Validators.required, // This is a sync validator
loginValidator, // This is a custom async validator
{
validator: Validators.required, // This is a sync validator
customArgs: { otherField: 'other' },
message: 'Required field',
},
{
validator: loginValidator, // This is a custom async validator
customArgs: { 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 },
},
],
},
};

field-validator

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:

const validationSchema: ValidationSchema = {
record: {
myRecordName: [
freeShippingAllowed, // This is a custom sync validator
asyncFreeShippingAllowed, // This is a custom async validator
{
validator: freeShippingAllowed, // This is a sync validator
message: 'Total must be greater than 30USD',
},
{
validator: asyncFreeShippingAllowed, // This is a custom async validator
message: 'Total must be greater than 60USD',
},
],
},
};

FullRecordValidation

Structure to define a record validation:

Properties:

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],
},
};

record-validator

createFormValidation

Factory method creates a new FormValidation. This is the main entry point when creating FormValidations

Arguments:

Returned Value

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:

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:

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:

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.

Arguments:

  • values: all form values (e.g. in a login form, values would be username and password fields).

Returns:

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

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

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

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

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:

required

You can find this example in javascript example and typescript example.

email

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:

email

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:

pattern

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:

min-length

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:

max-length

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:

array

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

custom-validators

Async custom validators

async-validator