{"id":17039550,"url":"https://github.com/selbekk/calidation","last_synced_at":"2025-04-05T10:07:39.358Z","repository":{"id":38272762,"uuid":"128120660","full_name":"selbekk/calidation","owner":"selbekk","description":"Red hot form validation for React 🌶","archived":false,"fork":false,"pushed_at":"2022-12-08T17:01:52.000Z","size":3968,"stargazers_count":241,"open_issues_count":20,"forks_count":19,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-03-29T09:10:39.527Z","etag":null,"topics":["react","validation"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/selbekk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-04T20:53:14.000Z","updated_at":"2023-08-28T15:45:35.000Z","dependencies_parsed_at":"2023-01-25T15:00:11.028Z","dependency_job_id":null,"html_url":"https://github.com/selbekk/calidation","commit_stats":null,"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/selbekk%2Fcalidation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/selbekk%2Fcalidation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/selbekk%2Fcalidation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/selbekk%2Fcalidation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/selbekk","download_url":"https://codeload.github.com/selbekk/calidation/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247318744,"owners_count":20919484,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["react","validation"],"created_at":"2024-10-14T09:06:41.999Z","updated_at":"2025-04-05T10:07:39.339Z","avatar_url":"https://github.com/selbekk.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# calidation\n\nRed hot validation for React 🌶\n\n[![Build Status](https://travis-ci.org/selbekk/calidation.svg?branch=master)](https://travis-ci.org/selbekk/calidation) [![codecov](https://codecov.io/gh/selbekk/calidation/branch/master/graph/badge.svg)](https://codecov.io/gh/selbekk/calidation) [![npm version](https://badge.fury.io/js/calidation.svg)](https://badge.fury.io/js/calidation)\n\n```\nyarn add calidation\n```\n\n## What's this?\n\nThis is a validation library for React! It provides you with powerful and\nflexible validation, which is probably what you're looking for.\n\nI have written [the best blog post](https://medium.com/@selbekk/introducing-calidation-7d9a79453f7)\nof all time about this.\n\n## How do you even?\n\nLet's say you have a form you want to validate. Remove that old school\n`\u003cform /\u003e` tag and replace it with a fly af `\u003cFormValidation /\u003e` component!\n\n### Step 1: Specify your fields\n\nFirst, you specify a config object that specifies the names of the fields you\nwant to validate, and the validators to apply to each field.\n\n```js\nconst formConfig = {\n    username: {\n        isRequired: 'Username is required!',\n    },\n    password: {\n        isRequired: 'Password is also required!',\n        isMinLength: {\n            message: 'Password must at least be 8 characters long',\n            length: 8,\n        },\n    },\n};\n```\n\nIn this config, we validate two fields - `username` and `password`. These keys\nare matched with your `\u003cinput name /\u003e` property. Each matching object is a list\nof validators.\n\nHere, the key is the name of the validator, and the value is either the error\nmessage as a string, or an object with a simple validation configuration.\nYou can add as many validators as you want, and they'll be run from top to\nbottom. For more about validators, go to the [validators](#validators) section!\n\n### Validate that form\n\nAlright, so this is how it looks:\n\n```js\nimport { FormValidation } from 'calidation';\n\nconst config = {...}; // See above\nconst MyForm = props =\u003e (\n    \u003cFormValidation onSubmit={props.onSubmit} config={config}\u003e\n        {({ errors, fields, submitted }) =\u003e (\n            \u003c\u003e\n                \u003clabel\u003e\n                    Username: \u003cinput name=\"username\" value={fields.username} /\u003e\n                    {submitted \u0026\u0026 errors.username \u0026\u0026 \u003cspan\u003e{errors.username}\u003c/span\u003e}\n                \u003c/label\u003e\n                \u003clabel\u003e\n                    Password: \u003cinput name=\"password\" value={fields.password} /\u003e\n                    {submitted \u0026\u0026 errors.password \u0026\u0026 \u003cspan\u003e{errors.password}\u003c/span\u003e}\n                \u003c/label\u003e\n                \u003cbutton\u003eLog in\u003c/button\u003e\n            \u003c/\u003e\n        )}\n    \u003c/FormValidation\u003e\n);\n```\n\nThe `\u003cFormValidation /\u003e` component accepts a function as a child, which is\ncalled with an options object containing field values, errors and so on.\n\nThe `\u003cFormValidation /\u003e` component renders a `\u003cform /\u003e` tag, so you get a nicer\nuser experience out of the box! You can pass an `onSubmit` event handler, which\nwill be called with the field values and errors:\n\n```js\nonSubmit = ({ fields, isValid }) =\u003e {\n    if (isValid) {\n        server.saveAllTheData(fields);\n    }\n};\n```\n\n### Validate complex forms\n\nSome times, you end up with advanced forms, and you don't want to specify all\nthe fields in the same configuration object. There might be many reasons for\nthis, like when certain parts of your form is visible only if certain conditions\nare met.\n\nFor those cases, we have two new components - `\u003cForm /\u003e` and `\u003cValidation /\u003e`.\n\nThe `\u003cForm /\u003e` component works as the `\u003cform /\u003e` HTML tag, wrapping the entire\ncomplex form. You can put this at the top level of your page container\ncomponent, for example. This component accepts an `onSubmit` handler, similar to\nwhat you're used to from `\u003cFormValidation /\u003e`.\n\nThe `\u003cValidation /\u003e` component is a descendant of a given `\u003cForm /\u003e` component,\nand wraps your input fields, dropdowns and radio buttons. It expects a\n`config` prop, an optional `initialFields` prop, and a function as a child, just\nlike `\u003cFormValidation /\u003e`. Here\n\nHere's an example:\n\n```js\nimport { Form, Validation } from 'calidation';\nconst MyPage = props =\u003e (\n    \u003cForm onSubmit={props.onSubmit}\u003e\n        \u003cValidation config={props.config}\u003e\n            {({ fields }) =\u003e (\n                \u003c\u003e\n                    Who is your daddy?\n                    \u003cinput name=\"daddy\" value={fields.daddy} /\u003e\n                \u003c/\u003e\n            )}\n        \u003c/Validation\u003e\n        {/* ...tons of other components and other stuff */}\n        \u003cValidation config={props.anotherConfig}\u003e\n            {({ fields }) =\u003e (\n                \u003c\u003e\n                    What does he do?\n                    \u003cinput name=\"dadWork\" value={fields.dadWork} /\u003e\n                \u003c/\u003e\n            )}\n        \u003c/Validation\u003e\n    \u003c/Form\u003e\n);\n```\n\nThe `onSubmit` handler will receive a merged object of all the validated fields\nbelow it, as well as a merged object of all the errors:\n\n```js\nconst onSubmit = ({ fields, errors, isValid }) =\u003e {\n    // fields and errors now contain both `daddy` and `dadWork`\n    // isValid is true if all forms are valid, otherwise false.\n};\n```\n\n## Validators\n\nAll validators require a configuration object that looks like this:\n\n```js\nsomeField: {\n    isRequired: {\n        message: 'This is the error message shown if the validation fails',\n    },\n},\n```\n\nIf you only specify the `message` key, you can just pass the message string\ndirectly, like this:\n\n```js\nsomeField: {\n    isRequired: 'This is the error message shown if the validation fails',\n},\n```\n\nYou can skip validation of a certain validator if you specify a `validateIf`\nfunction. It will receive the other validated fields as an argument.\n\n```js\nsomeField: {\n    isRequired: {\n        message: 'You need to answer this question',\n        validateIf: ({ fields }) =\u003e fields.someOtherField === 'foo',\n    },\n},\n```\n\nIf you only want to display errors when the field has been edited, you can use the `isDirty` flag.\n\n```js\nsomeField: {\n    isMinLength: {\n        length: 5,\n        message: 'Must be minimum of 5 characters',\n        validateIf: ({ isDirty }) =\u003e isDirty,\n    },\n},\n```\n\nIf you want to do cross validation, or just need access to the other field inputs and / or errors, each validator also\naccepts a function that receives all fields and the current error state.\n\n```js\npassword: {\n    isRequired: 'You need a password',\n},\nrepeatPassword: {\n    isRequired: 'Please fill out the password a second time',\n    isEqual: ({ fields }) =\u003e ({\n        message: 'The two password must match',\n        value: fields.password,\n        validateIf: fields.password.length \u003e 0, // this can be a boolean too!\n    }),\n}\n```\n\nFinally, please note that validation happens from top to bottom. The validation\nwill quit once it encounters an error, so you can have multiple levels of\nvalidators if you so please.\n\n### Default validators\n\ncalidation comes with a lot of validators built in. These should be enough for\nmost common use-cases. You'll find them all in the sister package\n[`calidators`](https://github.com/selbekk/calidators).\n\n#### `isRequired`\n\nValidates that a field has some content.\n\n```js\nsomeField: {\n    isRequired: 'This field is required', // shorthand\n    isRequired: { message: 'This field is required' },\n},\n```\n\n#### `isNumber`\n\nValidates that a field only contains numeric characters\n\n```js\nsomeField: {\n    isNumber: 'You need to enter a number', // shorthand\n    isNumber: { message: 'You need to enter a number' },\n},\n```\n\n#### `isEqual`\n\nValidates that a field equals a given value. The value is cast to a String,\nand then checked for equality with the `===` operator.\n\n```js\nsomeField: {\n    isEqual: {\n        message: 'You need to enter \"yes\"',\n        value: 'yes',\n    },\n},\n```\n\n#### `isGreaterThan` / `isLessThan`\n\nValidates that a field is greater or less than a given number.\n\n```js\nsomeField: {\n    isGreaterThan: {\n        message: 'You need to be at least 18 years old',\n        value: 17,\n    },\n    isLessThan: {\n        message: 'You can\\'t be older than 70 years old',\n        value: 66,\n    },\n},\n```\n\n#### `isEmail`\n\nValidates that a field is a potentially valid email address.\n\n```js\nsomeField: {\n    isEmail: 'Please enter a valid e-mail address', // Shorthand\n    isEmail: { message: 'Please enter a valid e-mail address' },\n},\n```\n\n#### `isRegexMatch`\n\nValidates that a field matches a given regular expression.\n\n```js\nsomeField: {\n    isRegexMatch: {\n        message: 'You need to enter four digits',\n        regex: /^\\d{4}$/,\n    },\n},\n```\n\n#### `isWhitelisted`\n\nValidates that a field is present in a provided whitelist. The whitelist must be\nan array.\n\n```js\nfirstName: {\n    isWhitelisted : {\n        message: 'Bros only, bro',\n        whitelist: ['Chad', 'Bret'],\n    },\n},\n```\n\n#### `isBlacklisted`\n\nValidates that a field is not present in a provided blacklist. The blacklist\nmust be an array.\n\n```js\nfirstName: {\n    isBlacklisted : {\n        message: 'Bros are not welcome',\n        blacklist: ['Chad', 'Bret'],\n    },\n},\n```\n\n#### `isMinLength`\n\nValidates that a field is at least a given number of characters long.\n\n```js\nsomeField: {\n    isMinLength: {\n        message: 'You need at least four characters',\n        length: 4,\n    },\n},\n```\n\n#### `isMaxLength`\n\nValidates that a field is at most a given number of characters long.\n\n```js\nsomeField: {\n    isMaxLength: {\n        message: 'You can at most have four characters',\n        length: 4,\n    },\n},\n```\n\n#### `isExactLength`\n\nValidates that a field is exactly a given number of characters long.\n\n```js\nsomeField: {\n    isExactLength: {\n        message: 'Norwegian postal codes are four digits long',\n        length: 4,\n    },\n},\n```\n\n### Custom validators\n\nYou can add your own too! In that case, wrap your app with the\n`\u003cValidatorsProvider /\u003e` component, and pass it an object with your custom\nvalidators. It can look like this:\n\n```js\nimport { ValidatorsProvider } from 'calidation';\nconst extraValidators = {\n    isEven: (config, { errors, fields, isDirty }) =\u003e value =\u003e\n        Number(value) % 2 !== 0 ? config.message : null,\n    isOdd: (config, { errors, fields, isDirty }) =\u003e value =\u003e\n        Number(value) % 2 !== 1 ? config.message : null,\n};\n\n\u003cValidatorsProvider validators={extraValidators}\u003e\n    \u003cApp /\u003e\n\u003c/ValidatorsProvider\u003e;\n```\n\nSee how I implemented those custom validators? It's a curried function that\nfirst receives a config object, then the value, and then returns either an\nerror message or `null`. You might want to let them accept the empty string too,\nin case your field is not required.\n\n## API\n\n### `FormValidation`\n\n`import { FormValidation } from 'calidators';`\n\nWhen you have a simple form to validate.\n\n#### Props\n\nAccepts all of the props from `Form` and `Validation` below.\n\n#### Context\n\nThe `FormContext` object represents the core internal state of the form and is passed through event callbacks and into template functions.\n\n```js\n{\n    dirty: object, // Object with all fields isDirty state, keyed per field\n    errors: object, // Object with all error messages, keyed per field\n    fields: object, // Object with all field inputs, keyed per field\n    isValid: bool, // Boolean indicating whether your form is valid or not\n    resetAll: func, // call this to programmatically trigger a full state reset\n    setError: func, // callback accepting a diff object, updating errors like setState\n    setField: func, // callback accepting a diff object, updating fields like setState\n    submit: func, // call this to programmatically trigger a submitted state\n    submitted: bool, // flag showing whether the form has been submitted once or not\n}\n```\n\n### `Form`\n\n`import { Form } from 'calidators';`\n\nWhen you want to wrap a complex form (in conjunction)\n\n#### Props\n\n##### `onChange: func`\n\nThis callback is fired whenever a form change event is triggered. This could happen on any input\nin the form, not necessarily associated with a validated input. This callback is also called before\nany state changes have been made.\n\nThe `onChange` function is called with the original change event as its only prop.\n\n##### `onReset: func`\n\nThis callback is fired whenever the form is reset. That can happen whenever somebody clicks a button with type \"reset\",\nor calls the `resetAll` function passed in the `children` function.\n\nThe `onReset` function is called with no parameters.\n\n##### `onSubmit: func`\n\nThis callback is fired whenever the form is submitted. That can happen whenever\nsomebody clicks the submit button, hits `enter` in the form, or calls the `submit` function passed in the `children`\nfunction.\n\nThe `onSubmit` function is called with the `FormContext` object as its only prop.\n\n##### `onUpdate: func`\n\nThis callback is fired whenever the form state changes. This can happen when `Validation` components\nare `register`ed or `unregister`ed, when a field is updated by the user or when the `setField` method is called,\nwhen the `setError` method is called, or when the form is reset or the `resetAll` method is called.\n\nThe `onUpdate` function is called with the `FormContext` object as its only prop.\n\n### `Validation`\n\n`import { Validation } from 'calidators';`\n\nWhen you want to wrap a sub-set of your form in validation logic (in conjunction\nwith the `Form` tag)\n\n#### Props\n\n##### `children: func.isRequired`\n\nThe `children` function is called with the `FormContext` object as its only prop.\n\n##### `config: object.isRequired`\n\nThe config object specifies what you want to validate, and which validators to\napply to it.\n\nEach validator can accept an object with a `message` key or - in the case where\nyou don't have to specify anything other than a validation message - just a\nstring with the error message.\n\n##### `initialValues: object`\n\nThe `initialValues` object lets you specify the initial values of the form\nfields. These values are available from the `fields` argument in the `children`\nfunction, which lets you control your form fields.\n\n##### `transforms: object`\n\nThe `transforms` object lets you apply transforms to the value before it\nis stored and validated against. Each key should map to a field name and be a function\nthat receives and returns a value. This is useful if you wish to convert a value's\ntype or enforce casing.\n\n```js\n{\n    foo: (value) =\u003e parseInt(value),\n    bar: (value) =\u003e !!value ? 'YES' : 'NO',\n    etc: (value) =\u003e value.toLowerCase(),\n}\n```\n\n### `ValidatorsProvider`\n\n`import { ValidatorsProvider } from 'calidators';`\n\nWhen you want to provide your application with a few more validators. Wrap your\napp with this at the top level.\n\n#### Props\n\n##### `validators: object`\n\nAn object with functions according to the\n[validators](https://github.com/selbekk/calidators) spec. TL;DR: A function that\nreturns a function that returns a function that decides whether or not your\ninput if fair. Relax - here's an example:\n\n```js\nconst validators = {\n    isBadTaste = (config, context) =\u003e value =\u003e value === 'Justin Bieber',\n};\n\n\u003cValidatorsProvider validators={validators}\u003e\n    {...}\n\u003c/ValidatorsProvider\u003e\n```\n\nThe `context` is an object with the following props:\n\n```js\n{\n    errors: object, // object with the same keys as `fields`, but with error messages\n    fields: object, // object with the form field values, to make controlled components\n    isDirty: bool, // flag showing whether the current field has been modified\n}\n```\n\n## Want to contribute?\n\nI'd love some help! Report bugs, help me document stuff, create new validators\nand add new features!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fselbekk%2Fcalidation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fselbekk%2Fcalidation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fselbekk%2Fcalidation/lists"}