
js-validation is a vanilla JavaScript version of the jQuery Validation plugin that validates HTML form fields with built-in rules, custom messages, and submit callbacks.
It helps you add client-side form validation to signup forms, contact forms, account settings pages, and file upload forms. Supports npm, CDN, UMD, and ES module usage.
Features:
- Validate required fields and common input formats.
- Check email addresses, URLs, dates, numbers, and patterns.
- Compare related fields in the same form.
- Limit selected file count and file size.
- Add custom validators for project-specific rules.
- Import only selected rules in bundle-based projects.
- Show inline error messages near invalid fields.
- Update invalid field state during user input.
Use Cases
- Validating a registration form with required fields, email format, and password confirmation.
- Enforcing file input rules such as maximum file count and individual file size.
- Checking text inputs for strict patterns like numeric IDs, IPv4 addresses, or ISO dates.
- Adding client-side guardrails before an API submission without pulling in a UI framework.
How To Use It:
Installation
Install the js-validation from npm for Vite, webpack, Rollup, and other build-tool workflows.
npm install @phpdevsr/js-validation
Use the CDN build for direct browser usage.
<script src="https://cdn.jsdelivr.net/npm/@phpdevsr/js-validation/dist/js-validation.min.js"></script>
You can also import it as an ES module directly in the document.
<script type="module"> import jsValidation from 'https://cdn.jsdelivr.net/npm/@phpdevsr/js-validation/dist/js-validation.esm.min.js'; </script>
Basic Usage
Create a form with named fields. The rule object uses those field names as keys.
<form id="memberForm">
<label>
Email
<input id="memberEmail" name="email" type="email">
</label>
<label>
Password
<input id="memberPassword" name="password" type="password">
</label>
<label>
Confirm Password
<input name="passwordConfirm" type="password">
</label>
<button type="submit">Create account</button>
</form>
2. Import jsValidation and initialize the library with validation rules.
import jsValidation from '@phpdevsr/js-validation';
const memberValidator = jsValidation('#memberForm', {
rules: {
email: {
required: true,
email: true
},
password: {
required: true,
minlength: 8
},
passwordConfirm: {
required: true,
equalTo: '#memberPassword'
}
},
messages: {
passwordConfirm: {
equalTo: 'Enter the same password again.'
}
}
});
// The callback runs only after every field passes validation.
memberValidator.submit(function (form) {
fetch('/accounts/create', {
method: 'POST',
body: new FormData(form)
});
});
Configuration Options
rules(object): Defines validation rules by form field name.messages(object): Defines custom error messages by field name and rule name.errorClass(string): Sets the CSS class added to invalid fields. The default class isis-invalid.errorElement(string): Sets the HTML element used for inline error messages. The default element isspan.errorElementClass(string): Sets the CSS class added to generated error message elements. The default class isinvalid-feedback.onkeyup(boolean): Controls input-time validation. Set it tofalseto validate only on submit or manual API calls.
Built-in Rules
required: Requires a non-empty value after trimming whitespace.email: Validates a basic email address format.minlength: Requires a minimum character count.maxlength: Limits the maximum character count.range: Requires a numeric value inside a minimum and maximum range.pattern: Tests the field value against a regular expression.equalTo: Requires the field value to match another field in the same form.notEqualTo: Requires the field value to differ from another field in the same form.numeric: Accepts only numeric digits.url: Validates URL input.date: Checks whether the value can create a valid JavaScript date.dateISO: Requires aYYYY-MM-DDorYYYY/MM/DDdate format.ipv4: Validates IPv4 addresses.ipv6: Validates IPv6 addresses.alphanumeric: Accepts letters, numbers, and underscores.maxfiles: Limits the number of selected files.maxsize: Limits each selected file by size.maxsizetotal: Limits the total size of all selected files.
API Methods
// Create a validator instance for a form selector or form element.
const validator = jsValidation('#profileEditor', {
rules: {
displayName: {
required: true
}
}
});
// Register a custom validation rule before it runs.
jsValidation.addMethod('startsWithUser', function (value) {
return String(value || '').startsWith('user-');
}, 'The value must start with user-.');
// Run code only after the form passes validation.
validator.submit(function (form) {
fetch('/profile/save', {
method: 'POST',
body: new FormData(form)
});
});
// Validate every supported field in the form.
const formIsValid = validator.validate();
// Validate one field manually.
const displayNameIsValid = validator.element(
document.querySelector('[name="displayName"]')
);
// Remove errors from every supported field in the form.
validator.resetForm();
// Show a custom error on a field.
validator.showError(
document.querySelector('[name="displayName"]'),
'Choose a public display name.'
);
// Clear the error state from a field.
validator.clearError(
document.querySelector('[name="displayName"]')
);
Events
js-validation exposes no custom event API. It attaches a native submit listener to the form and a native input listener to fields when input-time validation remains active.
const form = document.querySelector('#profileEditor');
// Native submit still belongs to the form element.
form.addEventListener('submit', function () {
console.log('The form submit event fired.');
});
// Native input events still fire on form fields.
form.addEventListener('input', function (event) {
console.log('Changed field:', event.target.name);
});
Advanced Usages
The UMD build exposes the validator through the global jsValidation object.
<form id="quoteRequest">
<input name="fullName" type="text">
<input name="workEmail" type="email">
<button type="submit">Request quote</button>
</form>
<script src="https://cdn.jsdelivr.net/npm/@phpdevsr/js-validation/dist/js-validation.min.js"></script>
<script>
const quoteValidator = jsValidation.default('#quoteRequest', {
rules: {
fullName: {
required: true,
minlength: 2
},
workEmail: {
required: true,
email: true
}
}
});
quoteValidator.submit(function (form) {
console.log(new FormData(form));
});
</script>
Import each rule file the form needs.
import jsValidation from '@phpdevsr/js-validation/core';
import '@phpdevsr/js-validation/rules/required';
import '@phpdevsr/js-validation/rules/email';
import '@phpdevsr/js-validation/rules/minlength';
const billingValidator = jsValidation('#billingProfile', {
rules: {
billingEmail: {
required: true,
email: true
},
companyName: {
required: true,
minlength: 3
}
}
});
billingValidator.submit(function (form) {
fetch('/billing/profile', {
method: 'POST',
body: new FormData(form)
});
});
Markup-driven forms can store validation rules in data attributes. JavaScript rules override data-attribute rules when both define the same validator.
<form id="newsletterForm">
<input
name="readerEmail"
type="email"
data-rule-required
data-rule-email
>
<button type="submit">Subscribe</button>
</form>
<script type="module">
import jsValidation from '@phpdevsr/js-validation';
jsValidation('#newsletterForm', {
messages: {
readerEmail: {
required: 'Add your email address before subscribing.'
}
}
}).submit(function (form) {
fetch('/newsletter/signup', {
method: 'POST',
body: new FormData(form)
});
});
</script>
File upload forms need checks before the browser sends large files. The file rules inspect the selected file list on the input element.
import jsValidation from '@phpdevsr/js-validation';
const uploadValidator = jsValidation('#portfolioUpload', {
rules: {
projectFiles: {
required: true,
maxfiles: 4,
maxsize: '3MB',
maxsizetotal: '10MB'
}
},
messages: {
projectFiles: {
maxfiles: 'Upload up to 4 files.',
maxsize: 'Each file must stay under 3MB.',
maxsizetotal: 'The upload batch must stay under 10MB.'
}
}
});
uploadValidator.submit(function (form) {
fetch('/portfolio/files', {
method: 'POST',
body: new FormData(form)
});
});
Custom business rules belong in a reusable validator method. Register the rule before the form instance validates the related field.
import jsValidation from '@phpdevsr/js-validation';
// Add a project-specific validator.
jsValidation.addMethod(
'companyDomain',
function (value) {
return /@example-company\.com$/i.test(String(value || '').trim());
},
'Use your company email address.'
);
const inviteValidator = jsValidation('#teamInviteForm', {
rules: {
teammateEmail: {
required: true,
email: true,
companyDomain: true
}
}
});
inviteValidator.submit(function (form) {
fetch('/team/invite', {
method: 'POST',
body: new FormData(form)
});
});
Implementation Tips
Each field must have a name attribute. The validator skips unnamed fields, disabled fields, and submit buttons.
Place fields inside a form element. The library reads form.elements, attaches the submit listener to the form, and searches related fields through the same form.
Add CSS for the invalid class and error message class. The library adds classes and inserts error elements, but your stylesheet controls the final visual design.
Set onkeyup to false for long forms or expensive custom checks. Manual validation still works through the public API.
Alternatives:
- 10 Best Pure JavaScript Form Validation Libraries
- Client-Side Declarative Form Validation using Strictly.js
- Custom HTML5 Form Validator In Vanilla JavaScript – Just-validate
- Beginner-Friendly JavaScript Form Validation Library – Trivule
- Lightweight Flexible Form Validation Engine – simpower-validation
FAQs:
Q: Why does validation skip one of my fields?
A: The field likely has no name attribute, uses type="submit", or has the disabled attribute. The validator only processes named, enabled form controls.
Q: Can I use js-validation with Bootstrap 5 without custom CSS?
A: Yes. The default errorClass of "is-invalid" and errorElementClass of "invalid-feedback" match Bootstrap’s form validation classes. Just include the Bootstrap CSS file.
Q: How do I revalidate a field when the user changes its value?
A: The library listens to the input event by default and calls element() on the changed field. You can disable this behavior by setting onkeyup: false in the options.
Q: How do I add a custom validation rule?
A: Call jsValidation.addMethod(name, validateFn, message). The validate function receives (value, param, element, validatorInstance) and must return a boolean.
Q: Does the library support asynchronous validation, such as checking a username on a server?
A: The built-in system is synchronous. To perform async checks, you would need to handle them separately and toggle field validity manually or call resetForm() after a custom validation flow.







