{"id":24302660,"url":"https://github.com/gtournie/redux-form-validators","last_synced_at":"2025-04-05T05:04:37.637Z","repository":{"id":15824601,"uuid":"78828510","full_name":"gtournie/redux-form-validators","owner":"gtournie","description":"redux-form-validators","archived":false,"fork":false,"pushed_at":"2023-03-01T16:40:30.000Z","size":2469,"stargazers_count":153,"open_issues_count":24,"forks_count":23,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-14T13:15:29.975Z","etag":null,"topics":["react","react-intl","redux","redux-form","validation","validators"],"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/gtournie.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-01-13T08:03:59.000Z","updated_at":"2024-06-18T13:51:27.578Z","dependencies_parsed_at":"2024-06-18T14:06:32.459Z","dependency_job_id":null,"html_url":"https://github.com/gtournie/redux-form-validators","commit_stats":{"total_commits":62,"total_committers":11,"mean_commits":5.636363636363637,"dds":0.6935483870967742,"last_synced_commit":"61f4c95770daef956048484395cc12a39b765fe5"},"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtournie%2Fredux-form-validators","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtournie%2Fredux-form-validators/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtournie%2Fredux-form-validators/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtournie%2Fredux-form-validators/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gtournie","download_url":"https://codeload.github.com/gtournie/redux-form-validators/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247289424,"owners_count":20914464,"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","react-intl","redux","redux-form","validation","validators"],"created_at":"2025-01-17T00:17:56.222Z","updated_at":"2025-04-05T05:04:37.613Z","avatar_url":"https://github.com/gtournie.png","language":"JavaScript","funding_links":["https://www.buymeacoffee.com/jCk0aHycU"],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/gtournie/redux-form-validators.svg?branch=master)](https://travis-ci.org/gtournie/redux-form-validators)\n[![Coverage Status](https://coveralls.io/repos/github/gtournie/redux-form-validators/badge.svg?branch=master)](https://coveralls.io/github/gtournie/redux-form-validators?branch=master)\n[![Peer Dependencies Status](https://david-dm.org/gtournie/redux-form-validators/peer-status.svg)](https://david-dm.org/gtournie/redux-form-validators/peer-status.svg)\n[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)\n[![npm version](https://img.shields.io/npm/v/redux-form-validators.svg?style=flat-square)](https://www.npmjs.com/package/redux-form-validators)\n[![npm downloads](https://img.shields.io/npm/dm/redux-form-validators.svg?style=flat-square)](https://www.npmjs.com/package/redux-form-validators)\n\n# redux-form-validators\n\nSimple validations with redux-form / [react-final-form](https://github.com/final-form/react-final-form). Heavily inspired by the rails validations.\n\n[Installation](#installation) | [Demo](#demo) | [Documentation](#documentation) | [☕️Send some love ❤️](#send-some-love)\n\n## Installation\n\n`npm install redux-form-validators`\n\n\u003e Note: For internationalization purposes, this package is compatible with [react-intl](https://github.com/yahoo/react-intl).\n\n## Demo\n\n[Live demo](https://codesandbox.io/s/n4n164zpo4) -\u003e FieldLevelValidationForm.js\n\nOr you can also run the example project. Just clone the repo, run `npm i -d \u0026\u0026 npm start` and then go to [http://localhost:3003/](http://localhost:3003/)\n\n## How to use\n\nIf you're already familiar with [redux-form](http://redux-form.com/) it should be pretty straight forward:\n\n### Field validation\n\n[This example](https://redux-form.com/8.2.0/examples/fieldlevelvalidation/) shows you how to set a field level validation with redux-form.\nThanks to `redux-form-validators`, you'll only have to pass the validators needed:\n\n```javascript\nimport { required, email } from 'redux-form-validators'\n\n\u003cField name=\"email\" type=\"email\" label=\"Email\"\n  component={renderField} validate={[required(), email()]} /\u003e\n```\n\nThat's it! =)\n\n### Sync validation\n\nNow let's replace the validate function of [this redux-form example](https://redux-form.com/8.2.0/examples/syncvalidation/):\n\n```javascript\nconst validate = validateForm({\n  username: [required(), length({ max: 15 })],\n  email: [required(), email()],\n  age: [\n    required(),\n    numericality({\n      int: true,\n      '\u003e=': 18,\n      msg: { '\u003e=': 'You must be at least 18 years old' },\n    }),\n  ],\n})\n```\n\n## Documentation\n\nValidators\n\n- [required / presence](#required-alias-presence)\n- [email](#email)\n- [numericality](#numericality)\n- [date](#date)\n- [length](#length)\n- [confirmation](#confirmation)\n- [format](#format)\n- [acceptance](#acceptance)\n- [inclusion](#inclusion)\n- [exclusion](#exclusion)\n- [absence](#absence)\n- [url](#url)\n- [file](#file)\n\nForm\n\n- [validateForm](#validateform)\n- [combine](#combine)\n\nMore\n\n- [default options](#default-options)\n- [memoization](#memoization)\n- [i18n and react-intl](#i18n-and-react-intl)\n- [default messages override](#default-messages-override)\n- [common validation options](#common-validation-options)\n- [conditional validation](#conditional-validation)\n- [adding a validator](#adding-a-validator)\n- [date helpers](#date-helpers)\n- [url helper](#url-helper)\n\n### required (alias: presence)\n\nValidates that the specified value is not empty. It uses the `trim()` method to check if the value is a blank string, that is, a string that is either empty or consists of whitespace.\n\n```javascript\n\u003cField name=\"login\" type=\"text\" label=\"Login\"\n  component={renderField} validate={required()} /\u003e\n```\n\nThe default error message is \"is required\". You can also pass custom message via the [message option](#common-validation-options).\n\n### email\n\nValidates that the specified value is a valid email address. It uses the `email.REG_EMAIL` regexp to check the value.\n\n```javascript\n\u003cField name=\"email\" type=\"email\" label=\"Email\"\n  component={renderField} validate={email()} /\u003e\n```\n\nThis validator also provides 2 options to check (case insensitive) the domain:\n- `domainWhitelist` - Specifies a list of domains allowed\n- `domainBlacklist` - Specifies a list of domains not allowed\n\nExamples\n\n```javascript\nemail({ domainWhitelist: ['GOOGLE.COM', 'outlook.*'] })\nemail({ domainWhitelist: ['*.fr'] })\n\n// Disposable email addresses\nemail({ domainBlacklist: ['yopmail.com', 'guerrillamail.*'] })\n```\n\nThe default error messages are:\n\n- \"is not a valid email\"\n- \"{domain} is not an accepted domain\"\n\n### numericality\n\nValidates that your value have only numeric values. By default, it will match an optional sign followed by an integral or floating point number. To specify that only integral numbers are allowed set `int` (or `integer`) to true.\n\n```javascript\n\u003cField name=\"lat\" type=\"text\" label=\"Latitude\"\n  component={renderField} validate={numericality()} /\u003e\n```\n\nBesides `int`, this validator also accepts the following options to add constraints to acceptable values:\n\n- `\u003e` (or `greaterThan`) - Specifies the value must be greater than the supplied value. The default error message for this option is \"must be greater than \\${count}\".\n- `\u003e=` (or `greaterThanOrEqualTo`) - Specifies the value must be greater than or equal to the supplied value. The default error message for this option is \"must be greater than or equal to \\${count}\".\n- `=` (or `equalTo`) - Specifies the value must be equal to the supplied value. The default error message for this option is \"must be equal to \\${count}\".\n- `!=` (or `otherThan`) - Specifies the value must be other than the supplied value. The default error message for this option is \"must be other than 4{count}\".\n- `\u003c` (or `lessThan`) - Specifies the value must be less than the supplied value. The default error message for this option is \"must be less than \\${count}\".\n- `\u003c=` (or `lessThanOrEqualTo`) - Specifies the value must be less than or equal to the supplied value. The default error message for this option is \"must be less than or equal to \\${count}\".\n- `odd` - Specifies the value must be an odd number if set to true. The default error message for this option is \"must be odd\".\n- `even` - Specifies the value must be an even number if set to true. The default error message for this option is \"must be even\".\n\nExamples\n\n```javascript\nnumericality({ int: true })\nnumericality({ '\u003e': 6 })\nnumericality({ '\u003e': 6, '\u003c=': 20 })\nnumericality({ int: true, odd: true })\n```\n\nThe default error messages are:\n\n- \"is not a number\"\n- \"must be greater than {number}\"\n- \"must be greater than or equal to {number}\"\n- \"must be equal to {number}\"\n- \"must be other than {number}\"\n- \"must be less than {number}\"\n- \"must be less than or equal to {number}\"\n- \"must be odd\"\n- \"must be even\"\n\n### date\n\nVery simple date validator. Limited to year, month and day validation (but it should mostly match your needs). Feel free to use a date manipulation lib to write a better date validator (see [add a validator](#adding-a-validator)).\n\n```javascript\n\u003cField name=\"date\" type=\"text\" label=\"Date\"\n  component={renderField} validate={date({ format: 'mm/dd/yyyy' })} /\u003e\n```\n\nAccepts the following options:\n\n- `format` - Specifies the format that should match the date string. Accepts only the current flags: `y`, `m` \u0026 `d`. The number of flags used represents the number of digits expected (e.g. `yyyy` expects 4 digits while `yy` expects 2). Format examples: `mm/dd/yyyy`, `dd/mm/yyyy`, `yyyy-mm-dd`, `mm/dd/yy`, `yyyy/mm`, `mm/dd`...\n- `ymd` - Allows you to customize the format, to be more readable in case you're using i18n. For instance, you could use `{ format: 'jj/mm/aaaa', ymd: 'amj' }` for a French format.\n\n(See [default options](#default-options) to set `format` and `ymd` globally)\n\nAnd the comparable options:\n\n- '=', '\u003e', '\u003e=', '\u003c', '\u003c='. All of these options accept either a Date object, a timestamp, or a function (which returns a Date or a timestamp). To avoid syncing issues, don't pass `new Date()` directly but wrap it in a function or just pass the string `'today'`. Note that these options are only available if these flags are present: `y` + `m` + `d` OR `y` + `m` OR just `y`)\n\nExamples\n\n```javascript\ndate({ format: 'mm/dd/yyyy' })\ndate({ format: 'mm/yyyy' })\ndate({ format: 'YYYY-MM-DD', ymd: 'YMD' })\ndate({ format: 'dd/mm/yyyy', '\u003c': new Date(2020, 0, 1), '\u003e=': new Date(1980, 0, 1) })\ndate({ format: 'mm/dd/yyyy', '\u003e': 'today', msg: 'must be in the future' })\ndate({ format: 'mm/dd/yyyy', '\u003c=': twentyYearsAgo, msg: 'you must be at least 20 years old' })\n\nfunction twentyYearsAgo() {\n  let d = new Date()\n  d.setFullYear(d.getFullYear() - 20)\n  return d\n}\n```\n\nThe default error messages are:\n\n- \"expected format: {format}\"\n- \"is not a valid date\" (e.g. Feb 29 2017)\n- \"should be {op} {date}\" (e.g. 'should be \u003e 01/14/2017')\n\nSee also [parseDate](#parsedate) \u0026 [formatDate](#formatdate)\n\n### length\n\nValidates the length of the value. It provides a variety of options, so you can specify length constraints in different ways:\n\n```javascript\n\u003cField name=\"name\" type=\"text\" label=\"Name\"\n  component={renderField} validate={length({ min: 2 })} /\u003e\n```\n\nThe possible length constraint options are:\n\n- `min` (or `minimum`) - The value cannot have less than the specified length.\n- `max` (or `maximum`) - The value cannot have more than the specified length.\n- `in` (or `within`) - The value length must be included in a given interval. The value for this option must be an array.\n- `is` (or `=`) - The value length must be equal to the given value.\n\nExamples\n\n```javascript\nlength({ minimum: 2 })\nlength({ min: 2, max: 8 })\nlength({ in: [2, 8] })\nlength({ is: 6 })\n```\n\nThe default error messages depend on the type of length validation being performed. You can personalize these messages using the `wrongLength`, `tooLong`, and `tooShort` options and \\${count} as a placeholder for the number corresponding to the length constraint being used. You can still use the `msg` (or `message`) option to specify an error message (don't forget to pluralize it).\n\n### confirmation\n\nYou should use this validator when you have two text fields that should receive exactly the same content. For example, you may want to confirm an email address or a password.\n\n```javascript\n\u003cField name=\"pass\" type=\"password\" label=\"Password\" component={renderField} /\u003e\n\u003cField name=\"confirmation\" type=\"password\" label=\"Confirmation\" component={renderField}\n    validate={confirmation({ field: 'pass', fieldLabel: 'Password' })} /\u003e\n\n// Within a FormSection\n\u003cFormSection name=\"section\"\u003e\n  \u003cField name=\"pass\" type=\"password\" label=\"Password\" component={renderField} /\u003e\n  \u003cField name=\"confirmation\" type=\"password\" label=\"Confirmation\" component={renderField}\n    validate={confirmation({ field: 'section.pass', fieldLabel: 'Password' })} /\u003e\n\u003c/FormSection\u003e\n```\n\nThere is also a `caseSensitive` option that you can use to define whether the confirmation constraint will be case sensitive or not. This option defaults to true (see [default options](#default-options)).\n\nExamples\n\n```javascript\nconfirmation({ field: 'email' })\nconfirmation({ field: 'section.email' })\nconfirmation({ field: 'email', fieldLabel: 'Email' })\nconfirmation({ field: 'email', fieldLabel: 'Email', caseSensitive: false })\n```\n\nThe default error message for this validator is \"doesn't match \\${fieldLabel || field}\".\n\n### format\n\nValidates the value by testing whether it match a given regular expression, which is specified using the `with` option.\n\n```javascript\n\u003cField name=\"legacyCode\" type=\"text\" label=\"Legacy Code\" component={renderField}\n  validate={format({ with: /^[a-z]+$/i, message: 'Only allows letters' })} /\u003e\n```\n\nAlternatively, you can require that the specified value does not match the regular expression by using the `without` option.\n\nExamples\n\n```javascript\nformat({ with: /[a-z0-9]/i })\nformat({ without: /#@%\u0026\\!\\:\\?\\+\\=/i }) // doesn't allow these chars: '#@%\u0026!:?+='\n```\n\nThe default error message is \"is invalid\".\n\n### acceptance\n\nThis method validates that a checkbox on the user interface was checked. This is typically used when the user needs to agree to your application's terms of service, confirm that some text is read, or any similar concept.\n\n```javascript\n\u003cField name=\"terms\" type=\"checkbox\" label=\"I accept the terms of service\"\n  component={renderField} validate={acceptance()} /\u003e\n```\n\nIt can also receive an `accept` option, which determines the allowed values that will be considered as accepted. It defaults to ['1', 'true'] (see [default options](#default-options)).\n\nExamples\n\n```javascript\nacceptance({ accept: 'yes' })\nacceptance({ accept: ['TRUE', 'accepted'] })\n```\n\nThe default error message for this validator is \"must be accepted\".\n\n### inclusion\n\nValidates that the value is included in a given set.\n\n```javascript\n\u003cField name=\"size\" type=\"text\" label=\"Size\" component={renderField}\n  validate={inclusion({ in: ['small', 'medium', 'large'] })} /\u003e\n```\n\nThe inclusion validator has an option `in` that receives the set of values that will be accepted. The `in` option has an alias called `within` that you can use for the same purpose, if you'd like to.\n\nThere is also a `caseSensitive` option that you can use to define whether the match will be case sensitive or not. This option defaults to true (see [default options](#default-options)).\n\nExamples\n\n```javascript\ninclusion({ in: [1, 2, 3, 4] })\ninclusion({ in: ['blue', 'white', 'red'], caseSensitive: false })\n```\n\nThe default error message for this validator is \"is not included in the list\".\n\n### exclusion\n\nValidates that the value is not included in a given set.\n\n```javascript\n\u003cField name=\"subdomain\" type=\"text\" label=\"Subdomain\"\n  component={renderField} validate={exclusion({ in: ['www', 'us', 'ca'] })} /\u003e\n```\n\nThe exclusion validator has an option `in` that receives the set of values that will not be accepted for the validated attributes. The `in` option has an alias called `within` that you can use for the same purpose, if you'd like to.\n\nThere is also a `caseSensitive` option that you can use to define whether the match will be case sensitive or not. This option defaults to true (see [default options](#default-options)).\n\nExamples\n\n```javascript\nexclusion({ in: [1, 2, 3, 4] })\nexclusion({ in: ['apple', 'banana'], caseSensitive: false })\n```\n\nThe default error message is \"\\${value} is reserved\".\n\n### absence\n\nValidates that the specified value are absent. It uses the `trim()` method to check if the value is not a blank string, that is, a string that is either empty or consists of whitespace.\n\n```javascript\n\u003cField name=\"name\" type=\"text\" label=\"Name\"\n  component={renderField} validate={absence()} /\u003e\n```\n\nThe default error message is \"must be blank\".\n\n### url\n\nValidates that the specified value is a valid URL.\n\n```javascript\n\u003cField name=\"url\" type=\"text\" label=\"URL\"\n  component={renderField} validate={url()} /\u003e\n```\n\nThe url validator has an option `protocol` (or its alias `protocols`) that receives the set of protocols that will be accepted. This option default to ['http', 'https'] (see [default options](#default-options)).\n\nThe other url constraint options are (all true by default):\n\n- `protocolIdentifier` - if set to false your URL doesn't have to start with `{{protocol}}://`\n- `emptyProtocol` - if set to false, doesn't accept URLs starting just with `//`\n- `basicAuth` - accepts or not basic authentication\n- `ipv4` - accepts or not an IPv4 address as a host\n- `ipv6` - accepts or not an IPv6 address as a host\n- `host` - accepts or not a domain + TLD as a host\n- `local` - accepts or not 'localhost' as a host\n- `port` - accepts or not a port\n- `path` - accepts or not a path\n- `search` - accepts or not a query string\n- `hash` - accepts or not a hash\n\nExamples\n\n```javascript\nurl({ protocols: ['http', 'https'] })\nurl({ protocol: 'http', ipv4: false, ipv6: false })\nurl({ protocol: 'ftp', port: false, basicAuth: false, hash: false })\n```\n\nThe default error message is \"is not a valid URL\".\n\nSee also [parseURL](#parseurl)\n\n\u003e Note: As of version 3.0.0, this method doesn't exclude any ip addresses anymore (like private \u0026 local networks). To re-implement this feature, you can use the [url.parseURL helper](#url-helper) and [add a custom validator](#adding-a-validator), like this:\n\n```javascript\n// Private and local networks not allowed\nconst REG = new RegExp(\n  '^(?:(?:10|127)(?:\\\\.\\\\d{1,3}){3})|' +\n    '(?:(?:169\\\\.254|192\\\\.168)(?:\\\\.\\\\d{1,3}){2})|' +\n    '(?:172\\\\.(?:1[6-9]|2\\\\d|3[0-1]))'\n)\n\nconst ipValidator = addValidator({\n  validator: function(options, value, allValues) {\n    let info = url.parseURL(value, options)\n    if (!info) return false\n    if (info.ipv4 \u0026\u0026 REG.test(info.ipv4)) {\n      return {\n        id: 'form.errors.private_url',\n        defaultMessage: 'Private and local networks are not allowed',\n      }\n    }\n  }\n})\n```\n\n### file\n\nValidates that the specified value is a valid File or FileList.\n\n```javascript\n\u003cField name=\"file\" type=\"file\" label=\"File\"\n  component={renderFileField} validate={file()} /\u003e\n```\n\nThe possible file constraint options are:\n\n- `accept` - The value is a file (or a list of files) that match a comma-separated list of allowed file extensions or MIME types\n- `minSize` - The value is a file (or a list of files) that cannot be smaller than the specified size\n- `maxSize` - The value is a file (or a list of files) that cannot be bigger than the specified size\n- `minFiles` - The value is a list of files that cannot be smaller than the specified length\n- `maxFiles` - The value is a list of files that cannot be bigger than the specified length\n\nExamples\n\n```javascript\nfile()\nfile({ accept: 'image/png, image/jpeg' })\nfile({ accept: '.png, .jpg, .jpeg' })\nfile({ accept: 'image/*' }) // Accept any file with an image/* MIME type\nfile({ minSize: '5 MB', maxSize: '1 TB' })\nfile({ minFiles: 2, maxFiles: 5 })\n```\n\nThe default error messages are:\n\n- \"is not a file\"\n- \"invalid file type\" / \"invalid file types ({count})\"\n- \"is too small (minimum is {size})\" / \"{count} files are too small (minimum is {size} each)\"\n- \"is too big (maximum is {size})\" / \"{count} files are too big (maximum is {size} each)\"\n- \"invalid number of files (minimum is {count})\"\n- \"invalid number of files (maximum is {count})\"\n\n\u003e Note: size units supported: B, KB, MB, GB, TB, PB, EB\n\n\u003e Note: file inputs are only compatible with `file`, `required` or `absence` validators\n\n\u003e Note: incorrect `minSize` or `maxSize` options will display an error in the console\n\n\u003e Note: for an optional file input, don't forget to pass `allowBlank: true`\n\n\n### validateForm\n\nHelper that turns a validation object into a validate function.\n\nExamples\n\n```javascript\nimport { required, length, validateForm } from 'redux-form-validators'\n\nconst validate = validateForm({\n  firstName: required(),\n  lastName: required(),\n  // FormSection\n  secureSection: {\n    password: [required(), length({ min: 8 }),\n    confirmation: confirmation({ field: 'secureSection.password' })\n  }\n})\n\n...\n\nexport default reduxForm({\n  form: 'validationFormExample',\n  validate,\n})(ValidationFormExample)\n```\n\n\u003e Note: For performance reasons, `validateForm` is not memoized. Use it always outside of the render function to avoid problems.\n\n### combine\n\nCombine several validators. This helper exists for 2 reasons:\n\n- when validators are combined using an array, it sometimes forces the component to be re-rendered (thank you @futpib for pointing it out). This is due to the way [React handle properties comparison](https://reactjs.org/docs/react-api.html#reactpurecomponent). [This demo](https://codesandbox.io/s/nwxm2w3544) shows the issue (see how the email field is forced to be re-rendered).\n- react-final-form doesn't support arrays of validators.\n\nExamples\n```javascript\n\u003cField name=\"email\" type=\"email\" label=\"Email\"\n  component={renderField} validate={combine(required(), email())} /\u003e\n\n\u003cField name=\"password\" type=\"password\" label=\"Password\"\n  component={renderField} validate={combine(required(), length({ min: 8 }))} /\u003e\n```\n\n\u003e Note: You don't need to use `combine` with `validateForm`\n\n### Default options\n\nredux-form-validators comes with default options:\n\n```javascript\n{\n  memoize:       true,\n  allowBlank:    false,\n  urlProtocols:  ['http', 'https'],\n  dateFormat:    'yyyy-mm-dd',\n  dateYmd:       'ymd',\n  accept:        ['1', 'true'],\n  caseSensitive: true,  // confirmation, inclusion, exclusion\n  pluralRules: { // See the \"i18n and react-intl\" section\n    0: 'zero',\n    1: 'one'\n  }\n};\n```\n\nBut you can easily change them:\n\n```javascript\nimport Validators from 'redux-validators'\n\n// Override dateFormat \u0026 urlProtocols\nObject.assign(Validators.defaultOptions, {\n  dateFormat: 'mm/dd/yyyy',\n  urlProtocols: ['http', 'https', 'ftp'],\n})\n```\n\n### Memoization\n\nSince version 7.0 of Redux-form, memoization is needed for inline validation. In some cases, you might want to disable it though. To do so:\n\n- set `Validators.defaultOptions.memoize` to false\n- OR set `memoize` validator's option to false (e.g. presence({ memoize: false }))\n\nAnd if you want to keep the memoization but want to override it:\n\n```javascript\n// Global memoization\n// This function usually returns a unique key depending on the options passed\n// $super represents the default memoize function\nValidators.defaultOptions.memoize = (options, $super) =\u003e {\n  return ... // string key\n}\n\n// Specific validation (inline-validation)\nlength({\n  min: 2,\n  if: () =\u003e this.state.foo,\n  memoize: (opts, $super) =\u003e $super(opts) + this.state.foo\n})\n\n// General validation\nconst validLen = length({ min: 2, if: () =\u003e ..., memoize: false })\n\n\u003cField name=\"test\" type=\"text\" label=\"Test\"\n  component={renderField} validate={validLen} /\u003e\n```\n\n### i18n and react-intl\n\nBy default, all errors messages are in english and are pluralized if needed (basic support) but you can use [react-intl](https://github.com/yahoo/react-intl) to support different languages. All you need to do is to insert the following lines:\n\n```javascript\nimport Validators from 'redux-form-validators'\nimport { FormattedMessage } from 'react-intl'\n\nValidators.formatMessage = function(msg) {\n  return \u003cFormattedMessage {...msg.props || msg} /\u003e\n}\n```\n\n\u003e Note: You can also implement your own i18n/pluralization module by overriding `Validators.formatMessage`. The first argument is a javascript object compatible with react-intl:\n\n```javascript\n{\n  id: \"form.errors.greaterThan\",\n  defaultMessage: \"must be greater than {count, number}\",\n  values: { count: 10 }\n}\n```\n\n\u003e Note: You can also change the default plural rules or file size formats:\n\n```javascript\n// Plural rules\nValidators.pluralRules = {\n  1: 'one', 5: 'one', 7: 'one', 8: 'one', 9: 'one', 10: 'one',\n  2: 'two', 3: 'two',\n  4: 'few',\n  6: 'many'\n}\nlet msg = '{count, plural, one {foo} two {bar} few {fooo} many {baaar} other {foobar}}'\n\n// Size format\nconst FR_UNITS = {\n  B:  'octets',\n  KB: 'Ko',\n  ...\n}\nValidators.formatSize = function (size, unit) {\n  return size + ' ' + FR_UNITS[unit]\n}\nfile({ minSize: '5MB' }) // -\u003e is too small (minimum is 5 Mo)\nfile({ minSize: 500 })   // -\u003e is too small (minimum is 500 octets)\n```\n\nAnd if you're using [babel-plugin-react-intl](https://github.com/yahoo/babel-plugin-react-intl) to extract your application messages, you'll need to **add** a new plugin entry in your webpack config ([example](https://github.com/gtournie/redux-form-validators/blob/master/webpack/example.js)):\n\n```javascript\n[\"react-intl\", {\n  \"messagesDir\": ...,\n  \"languages\": ...,\n  // /!\\ it's important to keep a relative path here\n  \"moduleSourceName\": \"./redux-form-validators\",\n}, 'redux-form-validators']\n```\n\n### Default messages override\n\nTo override the default messages globally:\n\n```javascript\nObject.assign(Validators.messages, {\n  email: {\n    id: \"form.errors.email\",\n    defaultMessage: \"is not a valid email address\"\n  },\n  presence: {\n    id: \"form.errors.presence\",\n    defaultMessage: \"is missing\"\n  },\n  tooShort: {\n    id: \"form.errors.tooShort\",\n    defaultMessage: \"is too short: {count, number} chars minimum\"\n  },\n  ...\n})\n```\n\nOR even simpler if you don't override formatMessage (and don't need ids):\n\n```javascript\nObject.assign(Validators.messages, {\n  email:    \"is not a valid email address\",\n  presence: \"is missing\",\n  tooShort: \"is too short: {count, number} chars minimum\",\n  ...\n})\n```\n\n\u003e Note: This won't work with react-intl, as you load the messages from a json file\n\n[See all default messages](https://github.com/gtournie/redux-form-validators/blob/master/src/messages.js).\n\n### Common validation options\n\n#### allowBlank\n\nThis option will let validation pass if the value is blank, like an empty string for example.\n\n```javascript\n\u003cField name=\"name\" type=\"text\" label=\"Name\" component={renderField}\n  validate={length({ '=': 5, allowBlank: true })} /\u003e\n```\n\nNot available for: required, absence, acceptance \u0026 confirmation.\n\n\u003e Note: If you're already using the required validator you don't need to care about the allowBlank option.\n\n#### message (alias: msg)\n\nAs you've already seen, the `message` option lets you specify the message that will be added to the errors collection when validation fails. When this option is not used, `redux-form-validators` will use the respective default error message for each validator. The `message` option accepts a String, a Hash or a [FormattedMessage](https://github.com/yahoo/react-intl/wiki/Components#string-formatting-components).\n\n```javascript\nformat({ with: /^[a-z]+$/i, message: 'Letters only' })\nformat({ with: /^[a-z]+$/i, message: {\n  defaultMessage: 'Letters only' } })\n\n// I18n with react-intl\nformat({ with: /^[a-z]+$/i, message: { id: 'form.errors.alpha',\n  defaultMessage: 'Letters only' } })\nformat({ with: /^[a-z]+$/i, message: \u003cFormattedMessage id=\"form.errors.alpha\"\n  defaultMessage=\"Letters only\" /\u003e })\n\n// Redefine only certain messages and use interpolation\nlength({ msg: { tooShort: 'too short', tooLong: 'too long' }, in: [2, 8] })\nlength({ msg: { tooShort: { id: 'errors.length.min',\n  defaultMessage: 'too short' } }, min: 2 })\nlength({ msg: { tooShort: \u003cFormattedMessage id=\"errors.length.min\"\n  defaultMessage=\"too short\" /\u003e }, min: 2 })\nlength({ msg: { tooShort: 'min {count, number} characters' }, min: 2, max: 8 })\n  //=\u003e tooLong message remains the default message\n\n// Version \u003e= 3.3.0 (aliases)\nlength({ msg: { min: 'too short', max: 'too long' }, in: [2, 8] })\nnumericality({ msg: { '\u003e=': 'must be at least {count, number} years old' }, '\u003e=': 18 })\ndate({ msg: { '\u003e': 'must be in the future' }, '\u003e': 'today' })\n```\n\n##### Message key aliases\n\nDate\n- 'dateFormat', 'format'\n- 'dateInvalid', 'invalid'\n- 'dateRange', 'range', '=', '!=', '\u003e', '\u003e=', '\u003c', '\u003c=' (operators only match with their specific validation)\n\nEmail\n- 'email', 'invalid'\n- 'emailDomain', 'domain'\n\nFile\n- 'fileTooFew', 'tooFew', 'minFiles'\n- 'fileTooMany', 'tooMany', 'maxFiles'\n- 'fileAccept', 'accept'\n- 'fileTooSmall', 'tooSmall', 'minSize'\n- 'fileTooBig', 'tooBig', 'maxSize'\n\nLength\n- 'wrongLength', 'is', '='\n- 'tooLong', 'maximum', 'max'\n- 'tooShort', 'minimum', 'min'\n\nNumericality\n- 'notANumber', 'NaN'\n- 'notAnInteger', 'int'\n- 'equalTo', '='\n- 'otherThan', '!='\n- 'greaterThan', '\u003e'\n- 'greaterThanOrEqualTo', '\u003e='\n- 'lessThan', '\u003c'\n- 'lessThanOrEqualTo', '\u003c='\n\n\n\u003e Note: all messages are internally converted into javascript objects (see [i18n and react-intl](#i18n-and-react-intl)), so if you pass a FormattedMessage as an argument, don't expect it to be returned as it.\n\n[See all default messages](https://github.com/gtournie/redux-form-validators/blob/master/src/messages.js).\n\n### Conditional validation\n\n#### Using a function with `if` and `unless`\n\nFinally, it's possible to associate `if` and `unless` with a function which will be called. Using a function gives you the ability to write an inline condition instead of a separate method. This option is best suited for one-liners.\n\n```javascript\n\u003cField name=\"surname\" type=\"text\" label=\"Surname\" component={renderField}\n  validate={presence({ if: (values, value, props, name) =\u003e '' !== values.name })} /\u003e\n```\n\n\u003e Note: In some cases, the memoization can mess with `if` and `unless` methods which can refer to out-of-the-scope variables. See [memoization](#memoization) for further information.\n\n### Adding a validator\n\n```javascript\nconst alphaValidator = addValidator({\n  defaultMessage: \"Letters only\",\n  validator: function(options, value, allValues) {\n    return (options.lowerCase ? /^[a-z]+$/ : /^[a-z]+$/i).test(value)\n  }\n})\n\n\u003cField name=\"name\" type=\"text\" label=\"Name\" component={renderField}\n    validate={alphaValidator({ lowerCase: true, allowBlank: true })} /\u003e\n\n// Version \u003e= 2.0.0 only\nconst digitValidator = addValidator({\n  validator: function(options, value, allValues) {\n    if (options.digits !== value.replace(/[^0-9]/g, '').length) {\n      return {\n        id: \"form.errors.custom\",\n        defaultMessage: \"must contain {count, number} {count, plural, one {digit} other {digits}})\",\n        values: { count: options.digits },\n      }\n    }\n  }\n})\n\n\u003cField name=\"digits\" type=\"text\" label=\"4 digits\"\n  component={renderField} validate={digitValidator({ digits: 4 })} /\u003e\n```\n\n`defaultMessage` accepts a String, a Hash or a [FormattedMessage](https://github.com/yahoo/react-intl/wiki/Components#string-formatting-components). See the `message` option. Its default value is `is not valid`.\n\n\u003e Note: As of version 2.0.0, you can now return a message directly if invalid (allowing things like pluralization). For backward compatibility, if you return a boolean, the validator will return the defaultMessage if invalid.\n\n\u003e Note: you'll still be able to use the common options (`message`, `allowBlank` \u0026 `memoize`) and the conditional validation (`if` and `unless`).\n\n### Date helpers\n\n#### parseDate\n\nparser used to validate dates.\n\nSignature: `parseDate(dateString, format[, ymd])`\n\nExamples:\n\n```javascript\nimport { date } from 'redux-form-validators'\nlet parseDate = date.parseDate\n\nparseDate('12/31/2017', 'mm/dd/yyyy')        =\u003e new Date(2017, 11, 31)\nparseDate('2016/01',    'yyyy/mm'))          =\u003e new Date(2016,  1,  1)\nparseDate('12/01',      'mm/dd'))            =\u003e new Date(1970, 11,  1)\n\n// Custom ymd\nparseDate('12/31/2017', 'mm/jj/aaaa', 'amj') =\u003e new Date(2017, 11, 31)\n\n// Error\nparseDate('12122016',   'mm/dd/yyyy')        =\u003e Invalid date\n```\n\n#### formatDate\n\nformatter used to display dates.\n\nSignature: `formatDate(date, format[, ymd])`\n\nExamples:\n\n```javascript\nimport { date } from 'redux-form-validators'\nlet formatDate = date.formatDate\n\nformatDate(new Date(2017, 11, 31), 'mm/dd/yyyy')        =\u003e '12/31/2017'\nformatDate(new Date(2016,  1,  1), 'yyyy/mm'))          =\u003e '2016/01'\nformatDate(new Date(1970, 11,  1), 'mm/dd'))            =\u003e '12/01'\n\n// Custom ymd\nformatDate(new Date(2017, 11, 31), 'mm/jj/aaaa', 'amj') =\u003e '12/31/2017'\n\n// Error\nformatDate(new Date(NaN), 'mm/dd/yyyy')                 =\u003e null\nformatDate(null,          'mm/dd/yyyy')                 =\u003e null\nformatDate({},            'mm/dd/yyyy')                 =\u003e null\n```\n\n### URL helper\n\n#### parseURL\n\nparser used to validate URLs\n\nSignature: `parseURL(url[, options])`\n\n- options are the same as described for [url](#url)\n- returns null if invalid\n- otherwise returns an object filled with the elements found\n\nExamples:\n\n```javascript\nimport { url } from 'redux-form-validators'\nlet parseURL = url.parseURL\n\nparseURL('http://example.com/stuff')\n// { protocol: 'http', host: 'example.com', path: '/stuff' }\n\nparseURL('http://localhost:8080')\n// { protocol: 'http', host: 'localhost', port: 8080 }\n\nparseURL('//212.78.3.17:4000')\n// { ipv4: '212.78.3.17', port: 4000 }\n\nparseURL('http://[::1]:3000')\n// { ipv6: '::1', port: 3000, protocol: 'http' }\n\nparseURL('http://userid:pass@example.com')\n// { basicAuth: { username: 'userid', password: 'pass' }, ... }\n```\n\n## Send some love:\n\nYou like this package?\n\n[![Buy me a coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/jCk0aHycU)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgtournie%2Fredux-form-validators","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgtournie%2Fredux-form-validators","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgtournie%2Fredux-form-validators/lists"}