npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

foval

v0.0.20

Published

Wonderfully easy form validation for Node.js.

Downloads

9

Readme

Foval

Wonderfully easy form validation for Node.js.

Foval saves you an immense amount of time by providing a quick, easy and solid framework for validating your form fields. It is completely asynchronous and supports a wide range of data transformations and validations out of the box. You can even add custom ones if you wish.

Quick Start

If you want to get started quickly, copy and paste the following code into your project:

var form = new Foval({   //pass in the data as a set of key-value pairs.
  'fullName':        'Josh Cole',
  'telephoneNumber': '+44.7912345678',
  'aboutText':       'Lorem ipsum...',
  'hoursNeeded':     30
});

form.defineFields({
  fieldName: 'fullName',
  dataType:  'string',
  trim:      true,
  required:  true,
  transforms: {
    before: {
      'str-case': 'capitalise'
    }
  }
}, {
  fieldName: 'telephoneNumber',
  dataType:  'tel',  //automatic validation.
  required:  true
}, {
  fieldName: 'email',
  dataType:  'email',  //automatic validation.
  required:  true
}, {
  fieldName: 'aboutText',
  dataType:  'string',
  transforms: {
    after: {
      'str-line-break-to-br': true
    }
  },
  validations: {
    'str-length': {
      min: 100,
      max: 300
    }
  }
}, {
  fieldName: 'hoursNeeded',
  dataType:  'int',
  validations: {
    'numeric': {
      min: 1,
      max: 50
    }
  }
});

form.validate(function (err, isFormValid, validationResults, fieldHash) {

  // A fatal error, not a validation error.
  if (err) { return ...  }

  // The form failed to validate.
  if (!isFormValid) {
    // Use 'validationResults' to check what went wrong.
    return ...
  }

  // Form is valid!
  console.log(fieldHash);  //use 'fieldHash' to access the values.

});

Full Guide

This section provides a full guide to form validation with Foval and explain each of the steps in more detail.

Data Types

Foval supports the following internal data types, some of which automatically apply transformations and validations. Raw input from the form is automatically typecast depending on the data type chosen, this is useful for example with numerical fields which are passed through as strings, but really should be integers or floats.

| Data Type | Becomes | Typecast | Transform | Validation | Notes | |--------------|-----------|----------|-----------|------------|-------------| | string | string | String | | | | | str | string | String | | | | | number | int | Number | | | | | int | int | Number | | | | | float | float | Number | | | | | email | email | String | str-trim | email | | | telephone | telephone | String | str-trim | telephone | | | tel | telephone | String | str-trim | telephone | | | url | url | String | str-trim | url | | | boolean | boolean | Boolean | | | | | bool | boolean | Boolean | | | | | checkbox | checkbox | Boolean | | | | | password | password | String | | | Plain-text. |

Defining Fields

In order to validate the form in a structured way you must first define each of the fields, the expected data types, validations you want to run, and any transformations you want to run on the data.

form.defineFields({
  fieldName:    'firstName',
  dataType:     'string',
  defaultValue: 'Bob',
  required:     true,
  trim:         true,
  modify: function (value, finish) {
    ...
    return finish(null, isValid, reason);
  },
  transforms: {
    before: {
      ...
    },
    after: {
      ...
    }
  },
  validations: {
    ...
  }
});

Shortcuts

When defining fields you might want to enable some transforms or validations on a regular basis. To save time you can use the following shortcuts.

Transforms

| Shortcut | Data Type | Default | Transform | When | |----------|-----------|---------|-----------|--------| | trim | Boolean | False | str-trim | Before | | modify | Function | Null | custom | Before |

Validations

| Shortcut | Data Type | Default | Validation | |----------|-----------|---------|------------| | required | Boolean | False | required |

Setting Up Transforms

Transforms allow you to modify the data in the field both 'before' and 'after' it is validated. This is useful for example, if you need to trim whitespace from an email before validating it, and then want to run a custom transform after validation. Transforms will be run in the order they are added. When defining a field you must add transforms inside the 'transforms.before' or 'transforms.after' property. The 'before' transforms will be run before any validation is attempted, and the 'after' transforms will be run after successful validation.

Use The Default Options

If you just pass 'true' the transform will be run with the default options. Please note some transforms have required options.

{
  ...
  transforms: {
    before: {
      'str-case': true
    },
    after: {
      ...
    }
  }
}

Specifying Options

You can also pass an object containing various options to the transform. The 'run' option is 'true' by default, if you set it to 'false' you can prevent the transform from running.

{
  ...
  ...
  transforms: {
    before: {
      'str-case': {
        run:  true,
        case: 'upper'
      }
    },
    after: {
      ...
    }
  }
}

Setting Up Validations

Validations allow you to test the field values against pre-defined rules. When defining a field you must add validations inside the 'validations' property. Validations will be run in the order they are added.

Use The Default Options

If you just pass 'true' the validation will be run with the default options. Please note some validations have required options.

{
  ...
  validations: {
    'password': true
  }
}

Specifying Options

You can also pass an object containing various options to the validation. The 'run' option is 'true' by default, if you set it to 'false' you can prevent the validation from running without invalidating the field.

{
  ...
  validations: {
    'password': {
      run: true,
      requirements: {
        length:    6,
        lowercase: true,
        uppercase: true,
        common:    true
      }
    }
  }
}

Transforms List

The following is a list of all the transforms and what they do. Remember, you can use these 'before' or 'after' the data is validated.

'custom'

Allows you to pass in an asynchronous function to do some transformation of the data.

Options

| Property | Data Type | Default | Notes | |----------|-----------|---------|------------------------------------------| | run | Boolean | True | Set false to stop the transform running. | | fn | Function | Null | The custom transform function. |

Function Parameters

| Parameter | Data Type | Notes | |-----------|-----------|-------------------------------------------------------| | value | Mixed | The value of the field. | | dataType | String | The Foval data type of the field. | | finish | Function | The callback to call when your function has finished. |

Finish Parameters

| Parameter | Data Type | Notes | |-------------------|-----------|-----------------------------------------------| | err | Error | An error to pass back or null. | | transformedValue | Mixed | The transformed/unchanged value to pass back. |

Example

{
  ...
  transforms: {
    before: {
      'custom': function (value, dataType, finish) {
        var transformedValue = value.replace(/a/gi, 'b');
        return finish(null, transformedValue);
      }
    }
  }
}, {
  ...
  transforms: {
    before: {
      'custom': {
        run: true,
        fn:  function (value, dataType, finish) {
          var transformedValue = value.replace(/a/gi, 'b');
          return finish(null, transformedValue);
        }
      }
    }
  }
}

'md5'

Creates an MD5 hash of the value. Non-string values will be typecast to strings first and this may have unexpected behaviour.

Options

| Property | Data Type | Default | Notes | |----------|-----------|---------|-------------------------------------------------------| | run | Boolean | True | Set false to stop the transform running. | | encoding | String | 'hex' | The encoding type. See Node's crypto documentation. | | seed | Mixed | Null | Any value to use as a seed, optional. | | random | Bool | False | Set true to add a random value to seed the hash with. |

Example

{
  ...
  transforms: {
    before: {
      'md5': 'hex'
    }
  }
}, {
  ...
  transforms: {
    before: {
      'md5': {
        run:      true,
        encoding: 'hex'
      }
    }
  }
}

'str-br-to-line-break'

Converts <br> tags to line breaks.

Options

| Property | Data Type | Default | Notes | |----------|-----------|---------|------------------------------------------| | run | Boolean | True | Set false to stop the transform running. |

Example

{
  ...
  transforms: {
    before: {
      'str-br-to-line-break': true
    }
  }
}, {
  ...
  transforms: {
    before: {
      'str-br-to-line-break': {
        run: true
      }
    }
  }
}

'str-case'

Change the case of a string.

Options

| Property | Data Type | Default | Notes | |----------|-----------|---------|------------------------------------------| | run | Boolean | True | Set false to stop the transform running. | | case | String | Null | The new string case to apply. |

Values For 'case'

| Case | Notes | |------------|-----------------------------------------------------------------------------| | uppper | Makes the whole string uppercase. | | lower | Makes the whole string lowercase. | | capitalise | Capitalises the first letter of each word whilst making the rest lowercase. | | capitalize | Capitalises the first letter of each word whilst making the rest lowercase. |

Example

{
  ...
  transforms: {
    before: {
      'str-case': 'upper'
    }
  }
}, {
  ...
  transforms: {
    before: {
      'str-case': {
        run:  true,
        case: 'upper'
      }
    }
  }
}

'str-collapse-whitespace'

Collapse multiple spaces or tabs into single spaces.

Options

| Property | Data Type | Default | Notes | |----------|-----------|---------|------------------------------------------| | run | Boolean | True | Set false to stop the transform running. |

Example

{
  ...
  transforms: {
    before: {
      'str-collapse-whitespace': true
    }
  }
}, {
  ...
  transforms: {
    before: {
      'str-collapse-whitespace': {
        run: true
      }
    }
  }
}

'str-line-break-to-br'

Converts line breaks tags to <br> tags.

Options

| Property | Data Type | Default | Notes | |----------|-----------|---------|------------------------------------------| | run | Boolean | True | Set false to stop the transform running. |

Example

{
  ...
  transforms: {
    before: {
      'str-line-break-to-br': true
    }
  }
}, {
  ...
  transforms: {
    before: {
      'str-line-break-to-br': {
        run: true
      }
    }
  }
}

'str-replace'

Replaces something in a string. Can be passed a regular expression or a string. If a string is passed in it will automatically be escape.

Options

| Property | Data Type | Default | Notes | |----------|---------------|---------|------------------------------------------| | run | Boolean | True | Set false to stop the transform running. | | find | RegExp/String | Null | The RegExp object or raw string to use. | | flags | Boolean | Null | Used if a string is passed to 'find'. | | replace | String | Null | The string to replace with. |

Example

{
  ...
  transforms: {
    before: {
      'str-replace': {
        run:     true,
        find:    'abc',
        flags:   'gi',
        replace: 'def'
      }
    }
  }
}

'str-trim'

Trims whitespace from the start and end of a string.

Options

| Property | Data Type | Default | Notes | |----------|-----------|---------|------------------------------------------| | run | Boolean | True | Set false to stop the transform running. |

Example

{
  ...
  transforms: {
    before: {
      'str-trim': true
    }
  }
}, {
  ...
  transforms: {
    before: {
      'str-trim': {
        run: true
      }
    }
  }
}

'telephone'

Formats a telephone number field as a friendly string.

Options

| Property | Data Type | Default | Notes | |---------------|-----------|---------|---------------------------------------------------------------------------------------------------| | run | Boolean | True | Set false to stop the transform running. | | pattern | String | Null | A Foval telephone pattern to use, overrides the 'format' option. | | format | String | 'basic' | The name of the quick format to use. | | international | Bool | Null | Set true to use international format or false to use local, otherwise we use the existing format. | | countryCode | String | Null | Must be provided if formatting local numbers as international, e.g. '44'. |

Instructions for 'pattern'

You can specify a custom pattern (as a string) to meet your requirements, for example:

  • "{ZERO}{REM}"
  • "{ZERO}{4} {REM}"
  • "+{CC} ({ZERO}) {3} {3} {REM}"

Patterns need to be a string, they can have any characters you wish except '{' or '}', and they must use the following flags:

| Flag | Notes | |--------|----------------------------------------------------------------------------------------| | {CC} | The country code in the number, otherwise the 'countryCode' option provided. | | {ZERO} | Inserts a zero if one if the next digit isn't a zero (use at the start of the number). | | {3} | The number of digits to use in this position, can be any number >0. | | {REM} | All the remaining numbers, this should be used last in the pattern. |

Values for 'format'

A list of pre-defined patterns to quickly format your number.

| Value | International Format | Local Format | |-------------|----------------------|---------------| | basic | +447912345678 | 07912345678 | | uk-local | +44 (0) 2035 123456 | 02035 123456 | | uk-business | +44 (0) 845 123 4567 | 0845 123 4567 |

Example

{
  ...
  transforms: {
    after: {
      'telephone': 'uk-business'
    }
  }
}, {
  ...
  transforms: {
    after: {
      'telephone': {
        run:         true,
        pattern:     'uk-business',
        countryCode: '44'
      }
    }
  }
}, {
  ...
  transforms: {
    after: {
      'telephone': {
        run:         true,
        pattern:     '+{CC} ({ZERO}) {3} {3} {REM}',
        countryCode: '44'
      }
    }
  }
}

Validations List

'custom'

Allows you to pass in an asynchronous function to do some validation of the data.

Options

| Property | Data Type | Default | Notes | |----------|-----------|---------|-------------------------------------------| | run | Boolean | True | Set false to stop the validation running. | | fn | Function | Null | The custom validation function. |

Function Parameters

| Parameter | Data Type | Notes | |------------|-----------|-------------------------------------------------------| | value | Mixed | The value of the field. | | dataType | String | The Foval data type of the field. | | isRequired | Boolean | Whether the field is required, as per the definition. | | finish | Function | The callback to call when your function has finished. |

Finish Parameters

| Parameter | Data Type | Notes | |-----------|-----------|------------------------------------------------------| | err | Error | An error to pass back or null. | | isValid | Boolean | Set true if the validation passed, otherwise false. | | reason | String | A short string denoting the failure reason, or Null. |

Example

{
  ...
  validations: {
    'custom': function (value, dataType, isRequired, finish) {
      ...
      return finish(null, isValid, reason);
    }
  }
}, {
  ...
  validations: {
    'custom': {
      run: true,
      fn:  function (value, dataType, isRequired, finish) {
        ...
        return finish(null, isValid, reason);
      }
    }
  }
}

'email'

Checks to ensure we have a valid email address.

Options

| Property | Data Type | Default | Notes | |----------|-----------|---------|-------------------------------------------| | run | Boolean | True | Set false to stop the validation running. |

Example

{
  ...
  validations: {
    'email': true
  }
}, {
  ...
  validations: {
    'email': {
      run: true
    }
  }
}

'in-list'

Checks to ensure we the field value is in the provided list (array). Most useful for strings but can be used for other data types.

Options

| Property | Data Type | Default | Notes | |----------|-----------|---------|-------------------------------------------| | run | Boolean | True | Set false to stop the validation running. | | list | Array | Null | An array of the values to test against. |

Example

{
  ...
  validations: {
    'in-list': ['abc', 'def', 'ghi', 'jkl']
  }
}, {
  ...
  validations: {
    'in-list': {
      run:  true,
      list: ['abc', 'def', 'ghi', 'jkl']
    }
  }
}

'match-field'

Checks to ensure the field matches against another field, by default we only test the value and not the type unless the 'strict' option is set. Most useful for strings but can be used for other data types.

Options

| Property | Data Type | Default | Notes | |------------|-----------|---------|-----------------------------------------------------------------------------| | run | Boolean | True | Set false to stop the validation running. | | matchField | String | Null | The name of the other field we must match. | | strict | Boolean | False | Set true to use the === operator and also check the Foval dataType matches. |

Example

{
  ...
  validations: {
    'match-field': 'password'
  }
}, {
  ...
  validations: {
    'match-field': {
      run:        true,
      matchField: 'password',
      strict:     true
    }
  }
}

'numeric'

Runs various numeric validations on a field, depending on the options given.

Options

| Property | Data Type | Default | Notes | |-----------|-----------|---------|---------------------------------------------| | run | Boolean | True | Set false to stop the validation running. | | min | Float | Null | The minimum number allowed. | | max | Float | Null | The maximum number allowed. | | allowZero | Float | True | Set false to disallow '0' as a valid value. |

Example

{
  ...
  validations: {
    'numeric': {
      run:       true,
      min:       -10,
      max:       10,
      allowZero: false
    }
  }
}

'password'

Uses the Countersign module to test the strength of the password.

Options

| Property | Data Type | Default | Notes | |--------------|-----------|---------|--------------------------------------------------------------------------------------| | run | Boolean | True | Set false to stop the validation running. | | requirements | Object | {} | Pass in any of the Countersign options. |

Default Requirements

See the Countersign documentation for the options you can use.

| Property | Value | |-----------|-------| | length | 6 | | lowercase | True | | uppercase | True | | common | True |

Example

{
  ...
  validations: {
    'password': true
  }
}, {
  ...
  validations: {
    'password': {
      run: true,
      requirements: {
        length:    6,
        lowercase: true,
        uppercase: true,
        common:    true
      }
    }
  }
}

'regexp'

Allows you to test the value of a field against a regular expression.

Options

| Property | Data Type | Default | Notes | |----------|---------------|---------|-------------------------------------------------------------------| | run | Boolean | True | Set false to stop the validation running. | | test | RegExp/String | Null | A regular expression object or a string. | | flags | String | Null | Allows you to set flags if 'test' is a string regular expression. |

Example

{
  ...
  validations: {
    'regexp': /[a-z0-9]+/gi
  }
}, {
  ...
  validations: {
    'regexp': {
      run:  true,
      test: /[a-z0-9]+/gi
    }
  }
}, {
  ...
  validations: {
    'regexp': {
      run:   true,
      test:  '[a-z]{0,' + qty + '}[0-9]+',
      flags: 'gi'
    }
  }
}

'required'

Used on fields that are required and tests to see if the field is actually populated. Returns a validation error if there is no value in the field, or the value isn't enough for the field to be considered populated. For example a required checkbox field needs a truthy value to be considered populated, a false value isn't enough and will fail this validation.

Options

| Property | Data Type | Default | Notes | |----------|-----------|---------|-------------------------------------------| | run | Boolean | True | Set false to stop the validation running. |

Example

{
  ...
  validations: {
    'required': true
  }
}, {
  ...
  validations: {
    'required': {
      run: true
    }
  }
}

'str-length'

Make sure the length of a string falls within a specific range.

Options

| Property | Data Type | Default | Notes | |----------|-----------|---------|-------------------------------------------| | run | Boolean | True | Set false to stop the validation running. | | min | Int | Null | The minimum number of characters allowed. | | max | Int | Null | The maximum number of characters allowed. |

Example

{
  ...
  validations: {
    'str-length': {
      run: true,
      min: 100,
      max: 300
    }
  }
}

'telephone'

Checks to ensure we have a valid telephone number. The validation will only pass if the telephone number is a string in one of these formats:

  • International Format: '+44.7912345678'
  • Local Format: '07912345678'

Options

| Property | Data Type | Default | Notes | |-----------|-----------|---------|-----------------------------------------------------------------------------------| | run | Boolean | True | Set false to stop the validation running. | | minDigits | Int | 1 | The minimum number of digits in the phone number, not including the country code. | | maxDigits | Int | Null | The maximum number of digits in the phone number, not including the country code. |

Example

{
  ...
  validations: {
    'telephone': true
  }
}, {
  ...
  validations: {
    'telephone': {
      run:       true,
      minDigits: 5,
      maxDigits: 11
    }
  }
}

'url'

Checks to ensure we have a valid URL.

Options

| Property | Data Type | Default | Notes | |-----------------|-----------|---------|---------------------------------------------------------------| | run | Boolean | True | Set false to stop the validation running. | | requireProtocol | Boolean | True | Set false to validate URLs that don't have a HTTP/S protocol. |

Example

{
  ...
  validations: {
    'url': true
  }
}, {
  ...
  validations: {
    'url': {
      run:             true,
      requireProtocol: false
    }
  }
}