{"id":21524895,"url":"https://github.com/degjs/formvalidation","last_synced_at":"2025-07-19T04:03:11.910Z","repository":{"id":14366798,"uuid":"72776444","full_name":"DEGJS/formValidation","owner":"DEGJS","description":"A modular, promise-based form validation plugin, free of third-party dependencies and built on top of native HTML5 validation.","archived":false,"fork":false,"pushed_at":"2023-01-03T15:16:30.000Z","size":1700,"stargazers_count":2,"open_issues_count":13,"forks_count":1,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-06-16T23:47:53.743Z","etag":null,"topics":["forms"],"latest_commit_sha":null,"homepage":"http://degjs.com/formValidation/index.html","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/DEGJS.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":"2016-11-03T18:50:00.000Z","updated_at":"2021-05-05T15:11:20.000Z","dependencies_parsed_at":"2023-01-13T17:54:42.209Z","dependency_job_id":null,"html_url":"https://github.com/DEGJS/formValidation","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/DEGJS/formValidation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DEGJS%2FformValidation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DEGJS%2FformValidation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DEGJS%2FformValidation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DEGJS%2FformValidation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DEGJS","download_url":"https://codeload.github.com/DEGJS/formValidation/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DEGJS%2FformValidation/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265887026,"owners_count":23844326,"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":["forms"],"created_at":"2024-11-24T01:30:22.499Z","updated_at":"2025-07-19T04:03:11.869Z","avatar_url":"https://github.com/DEGJS.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FormValidation\n![Run Tests](https://github.com/DEGJS/formValidation/workflows/Run%20Tests/badge.svg)\n\nA modular, promise-based form validation plugin, free of third-party dependencies and built on top of native HTML5 validation.\n\n* [Intro](#waitanother-validation-plugin)\n* [Installation](#installation)\n* [Dependencies](#dependencies)\n* [Usage](#usage)\n* [Options](#options)\n* [Methods](#methods)\n* [Helpful Hints](#helpful-hints)\n* [Common Use Case Examples](#common-use-case-examples)\n* [Configuring Error Messages](#configuring-error-messages)\n* [Rules](#rules)\n* [Writing Your Own Rule](#writing-your-own-rule)\n* [Browser Support](#browser-support)\n\n\n## Wait...ANOTHER validation plugin?\nYou're right; there's no shortage of form validation plugins to choose from. That said, this plugin was written to fulfill some specific needs and workflows that many other validation plugins lack, including:\n\n* No third-party dependencies (especially jQuery)\n* Written as an ES6 module.\n* Extensible, to allow new validation rules (also written as ES6 modules) to be easily written, installed and bundled as needed.\n* Built to progressively enhance HTML5 validation patterns whenever possible.\n* Promise-based, asynchronous validation rules.\n* The ability to add and remove fields from the validation instance on the fly.\n* Customizable error messaging that can be set at the field, form or rule level, on a field-by-field basis.\n\n## Installation\nformValidation is an ES6 module. Consequently, you might need an ES6 transpiler ([Babel](https://babeljs.io) is a nice one) as part of your Javascript workflow.\n\nIf you're already using NPM for your project, you can install formValidation with the following command:\n\n```\n$ npm install @degjs/form-validation\n```\n\nformValidation rule modules that are hosted on GitHub or NPM can similarly be installed:\n\n```\n$ npm install @degjs/form-validation-required\n```\n\n## Dependencies\nformValidation doesn't rely on any third-party dependencies, but does make use of three small dependencies from its own [DEGJS](http://degjs.com/) ecosystem. These dependencies will be automatically installed and configured if you install formValidation via NPM; however, if you install manually, you'll also need to manually include the [domUtils](https://github.com/DEGJS/domUtils), [objectUtils](https://github.com/DEGJS/objectUtils) and [scrollTo](https://github.com/DEGJS/scrollTo) DEGJS modules.\n\n## Usage\nformValidation is designed to be modular and does not include any rules modules out of the box. Therefore, you'll need to import and instantiate all of the rule modules needed for your form.\n\nSample Javascript:\n```js\nimport formValidation from \"@degjs/form-validation\";\n\n/* Import the Required and Pattern rule modules */\nimport pattern from \"@degjs/form-validation-pattern\";\nimport required from \"@degjs/form-validation-required\";\n\n/* Configure the rules array alongside other validation options. Default rule settings can be overridden at the rule level during instantiation by calling the rule as a function and passing it an options array. */\nconst validationOptions = {\n    rules: [\n        pattern,\n        required({\n            message: 'You idiot! This field is required!'\n        })\n    ]\n};\n\n/* Instantiate the formValidation module on an element */\nconst formElement = document.querySelector('.form');\nconst validationInst = formValidation(formElement, validationOptions);\n```\n\nSample Markup:\n```html\n\u003cform class=\"form\"\u003e\n    \u003cfieldset\u003e\n        \u003cdiv class=\"js-validation-field\"\u003e\n            \u003clabel for=\"zip\"\u003eZIP Code\u003c/label\u003e\n            \u003cinput type=\"text\" required pattern=\"^\\d{5}(-\\d{4})?$\" id=\"zip\" name=\"zip\"\u003e\n        \u003c/div\u003e\n        \u003cbutton type=\"submit\"\u003eSubmit\u003c/button\u003e\n    \u003c/fieldset\u003e\n\u003c/form\u003e\n```\n\n## Options\n\n#### options.rules\nType: `Array`  \nDefault: `null`  \nAn array of rule module names that should be registered with the validation instance. Each rule in the array must be imported before being instantiated. The rule can be instantiated by listing its name only, or as a function call with options.\n\n#### options.fieldSelector\nType: `String`  \nDefault: `.js-validation-field`  \nThe CSS selector for each field element. NOTE: only fields containing this selector will be included in the validation instance on page load.\n\n#### options.inputsSelector\nType: `String`  \nDefault: `input, select, textarea`  \nThe CSS selector for each field's input elements.\n\n#### options.errorsClass\nType: `String`  \nDefault: `validation-field__errors`  \nThe CSS class added to all error wrapper elements within each field. NOTE: An error wrapper element with this class is automatically added to fields that don't contain one.\n\n#### options.errorClass\nType: `String`  \nDefault: `validation-field__error`  \nThe CSS class added to individual errors, within each field's error wrapper element.\n\n#### options.hasErrorsClass\nType: `String`  \nDefault: `has-errors`  \nThe CSS class added to fields when an error is present.\n\n#### options.generatedIdPrefix\nType: `String`  \nDefault: `js-validation-field--`  \nformValidation automatically adds randomly generated IDs to fields that don't already have IDs (i.e., `\u003cdiv class=\"js-validation-field\" id=\"js-validation-field--9695013748541\"\u003e`). This option changes the string that preceds the randomly generated number.\n\n#### options.inputParentFieldIdAttr\nType: `String`  \nDefault: `data-validation-field-id`  \nThe data attribute name added to inputs, which corresponds with the ID of its parent field.\n\n#### options.scrollToErrorOnSubmit\nType: `Boolean`  \nDefault: `true`  \nScrolls the page to the first field containing an error when form validation fails. This may be useful on long forms. This option uses the DEGJS scrollTo module. More information on this dependency can be found [here](https://github.com/DEGJS/scrollTo).\n\n#### options.scrollToSpeed\nType: `Integer`  \nDefault: `500`  \nSets the scroll speed of the `scrollToErrorOnFormSubmit` option.\n\n#### options.scrollToEasing\nType: `String`  \nDefault: `easeIn`  \nSets the easing effect of the `scrollToErrorOnFormSubmit` option.\n\n#### options.defaultErrorMessage\nType: `String`  \nDefault: `Validation error.`  \nEssentially a worst-case scenario error message, should something go wrong with error messages set at the field, form and rule level. You'll probably never see this, but it's configurable, just in case.\n\n#### options.onFormValidationStart\nType: `Function`  \nDefault: `null`  \nReturns: `Object {fieldsArr, event}`  \nThe name of the callback fired when a form's validation begins.\n\n#### options.onFieldValidationStart\nType: `Function`  \nDefault: `null`  \nReturns: `Object {fieldsArr, event}`  \nThe name of the callback fired when a field's validation begins.\n\n#### options.onFormValidationSuccess\nType: `Function`  \nDefault: `null`  \nReturns: `Object {fieldsArr, event}`  \nThe name of the event fired when a form's validation passes.\n\n#### options.onFieldValidationSuccess\nType: `Function`  \nDefault: `null`  \nReturns: `Object {fieldsArr, event}`  \nThe name of the event fired when a field's validation passes.\n\n#### options.onFormValidationError\nType: `Function`  \nDefault: `null`  \nReturns: `Object {fieldsArr, event}`  \nThe name of the event fired when a form's validation fails.\n\n#### options.onFieldValidationError\nType: `Function`  \nDefault: `null`  \nReturns: `Object {fieldsArr, event}`  \nThe name of the event fired when a field's validation fails.\n\n## Methods\n\n### .addFields(els)\nParameters: `els`  \nAn element or array of elements to add to the validation instance.\n\n### .removeFields(els)\nParameters: `els`  \nAn element or array of elements to remove from the validation instance.\n\n### .reset()\nParameters: `none`  \nRemoves all registered fields from the validation instance.\n\n## Helpful Hints\n* If FormValidation is being used on your form, **never try to write other validation functionality in tandem with it**. FormValidation disables HTML5 form validation and swallows several form- and field-related events. Trying to write separate validation will cause unexpected side effects and make debugging very difficult. A better approach is to write a custom FormValidation rule to handle your additional validation. You can also leverage FormValidation's built-in events (`on[Form/Field]ValidationStart`, `on[Form/Field]ValidationSuccess`, and `on[Form/Field]ValidationError`) to write custom behavior during the form's validation lifecycle.\n* When writing custom rules, **avoid adding side effects to your rule whenever possible**. An example of a side effect would be querying or mutating the DOM within the rule's `.isRelevant()` or `.validate()` methods. Doing so makes the rule less reusable and can introduce validation behavior that's difficult to troubleshoot. Instead, place your custom logic within FormValidation's built-in event callbacks.\n* When writing a custom rule or configuring an existing rule's events, use `focusout` (not `blur`) as your \"input no longer focused\" event (the `blur` event doesn't bubble up and won't always work as expected).\n\n## Common Use Case Examples\n### Dynamically adding/removing fields from validation\n```js\nimport formValidation from \"@degjs/form-validation\";\n\nconst validationInst = formValidation();\nconst toggleElement = document.querySelector('.js-toggle');\n// By giving the dependent fields their own class, and not using the default class, \n// the field will not be automatically added to the validation instance on page load.\nconst dependentFields = [...document.querySelectorAll('.js-dependent-field')];\n\ntoggleElement.addEventListener('change', e =\u003e {\n  if (e.target.checked) {\n    validationInst.addFields(dependentFields);\n  } else {\n    validationInst.removeFields(dependentFields);\n});\n\n```\n```html\n\u003cform\u003e\n  \u003cinput class=\"js-toggle\" type=\"checkbox\"\u003e\n  \u003cdiv class=\"js-dependent-field\"\u003e\n    \u003cinput required /\u003e\n  \u003c/div\u003e\n\u003c/form\u003e\n```\n\n\n## Configuring Error Messages\nWhen an error occurs, formValidation follows a hierarchy to determine which error message to show. This allows fine-grained control over messaging on a field-by-field basis. Error messages will be chosen in the following order of importance:\n\n1. Messages set on the field element via a data attribute. The name of this attribute should be configurable within each rule, and is the same as the attribute at the form level.\n2. Messages set on the form element via a data attribute. The name of this attribute should be configurable within each rule, and is the same as the attribute at the field level.\n3. A default message set by default within each rule module. This message can also be overridden via the \"message\" property when instantiating the rule. \n4. A generic fallback message built into formValidation itself.\n\nAfter the correct error message has been determined, it's still possible to process the message before it's displayed (this can be useful when replacing tokens or characters in a message based on a user's input, for example). This can be done via the `postprocessMessage` method within the rule itself, or overridden as a `postprocessMessage` option when instantiating a rule (see the \"Writing Your Own Rule\" documentation for more information).\n\n## Rules\nSeveral prebuilt rule modules are available via [DEGJS](http://degjs.com), including:\n* [required](https://github.com/DEGJS/formValidation-required)\n* [pattern](https://github.com/DEGJS/formValidation-pattern)\n* [email](https://github.com/DEGJS/formValidation-email)\n* [minMaxLength](https://github.com/DEGJS/formValidation-minMaxLength)\n\n## Writing Your Own Rule\nBy following formValidation's rule API, you can also write your own rule module that's asynchronous, Promise-based and can fire on most common [DOM events](https://developer.mozilla.org/en-US/docs/Web/Events) (including form submission, which uses `Promise.all` to validate all of a validation instance's rules at once).\n\n### Anatomy of a Rule\nA rule module must return the following methods:\n\n**.settings()**  \nParameters: `none`  \nRequired: `yes`  \nReturns: `Object`  \nMust return an object containing the following properties:\n* *message (optional):* the default message the rule will display\n* *messageAttr (required):* the attribute that will be checked on the field and form elements for message overrides\n* *events (required):* an array of DOM event names on which the rule should fire\n\n**.isRelevant(field)**  \nParameters: `field`  \nRequired: `yes`  \nReturns: `Boolean`  \nMust return a boolean value indicating if the rule is relevant to an individual field.\n\n**.validate(matchingField)**  \nParameters: `field`  \nRequired: `yes`  \nReturns: `Promise`  \nPerhaps counterintuitively, the validate method should return a resolve() method, regardless of whether validation passes or fails.\n\nRules that pass validation should return a `valid: true` property within the resolve method's returned object:\n\n```js\nresolve({\n    valid: true\n});\n```\n\nRules that fail validation should also resolve the promise, but return a `valid: false` property within the returned object:\n\n```js\nresolve({\n    valid: false\n});\n```\n\nThe validate method should only reject the promise when there is a problem with the rule (i.e., when the field passed to it doesn't contain any input elements).\n\n**.postprocessMessage(msg)**  \nParameters: `msg`  \nRequired: `no`  \nReturns: `String`  \nMust return the message it's passed, optionally reformatted if needed. This method should also check for a `settings.postprocessMessage` function, which allows it to be overriden during rule instantiation.\n\n### Sample rule\n```js\nconst required = (options) =\u003e {\n\n    const defaults = {\n        message: 'This field is required.',\n        messageAttr: 'data-validation-required-message',\n        events: [\n            'focusout',\n            'submit'\n        ]\n    };\n    \n    let settings = Object.assign({}, defaults, options);\n\n    function getSettings() {\n        return settings;\n    }\n\n    function isRelevant(field) {\n        return field.inputEls.some(el =\u003e el.getAttribute('required') !== null);\n    }\n\n    function validate (field) {\n        return new Promise(function(resolve, reject) {\n            if (field.inputEls) {\n                resolve({\n                    valid: field.inputEls.some(el =\u003e el.value.length \u003e 0)\n                });\n            } else {\n                reject('required: No inputs set.');\n            }\n        });\n    }\n\n    function postprocessMessage(msg) {\n        if (settings.postprocessMessage \u0026\u0026 typeof settings.postprocessMessage === 'function') {\n            return settings.postprocessMessage(msg);\n\t} else {\n            return msg;\n        }\n    }\n\n    return {\n        settings: getSettings(),\n        isRelevant: isRelevant,\n        validate: validate,\n        postprocessMessage: postprocessMessage\n    };\n\n}\n\nexport default required;\n```\n\n\n## Browser Support\n\nformValidation depends on the following browser APIs:\n+ Array.find: [Documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find) | [Polyfill](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find#Polyfill)\n+ Array.filter: [Documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) | [Polyfill](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Polyfill)\n+ Array.prototype.some: [Documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some) | [Polyfill](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some#Polyfill)\n+ Object.assign: [Documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) | [Polyfill](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill)\n+ Array.from: [Documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from) | [Polyfill](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Polyfill)\n+ Array.prototype.reduce: [Documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) | [Polyfill](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Polyfill)\n\n\nTo support legacy browsers, you'll need to include polyfills for the above APIs.   \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdegjs%2Fformvalidation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdegjs%2Fformvalidation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdegjs%2Fformvalidation/lists"}