A lightweight, chainable JavaScript form validation library with zero dependencies. Simple API, powerful validation, works everywhere.
- ๐ Chainable API - Fluent, readable syntax
- ๐ฏ Zero Dependencies - Pure JavaScript, no bloat
- ๐ฆ Tiny Bundle - Less than 5KB minified + gzipped
- ๐จ Customizable - Create your own validation strategies
- ๐ง Framework Agnostic - Works with vanilla JS, React, Vue, etc.
- ๐ช TypeScript Support - Full type definitions included
- โฟ Accessible - WCAG compliant error messaging
- ๐ Browser Support - IE11+ and all modern browsers
npm install fast-form-validator<script src="https://unpkg.com/fast-form-validator@latest/UMD/ffv.min.js"></script><form id="signup-form">
<input type="email" id="email" />
<input type="password" id="password" />
<input type="date" id="dob" />
<button type="submit" id="submit-btn">Sign Up</button>
<div id="error-messages"></div>
</form>FFV.onEmail('email')
.onPassword('password', 8, 20)
.onDateOfBirth('dob', 18)
.displayErrorsHere('error-messages')
.onSuccess.removeFeedback()
.onSubmitButton('submit-btn', handleSubmit)
.validate();
function handleSubmit() {
console.log('Form is valid!');
// Submit your form data
}import { FastFormValidator } from 'fast-form-validator';
const validator = new FastFormValidator();
validator
.onEmail('email')
.onPassword('password', 8, 20)
.displayErrorsHere('error-messages')
.validate();Validates email format.
FFV.onEmail('email-field');Validates password with complexity requirements (uppercase, lowercase, digit).
FFV.onPassword('password-field', 8, 20);
// Defaults: min=6, max=15Validates age requirement.
FFV.onDateOfBirth('dob-field', 18);
// Default: minAge=18Create custom validation logic.
function validateUsername() {
const value = this.usernameValue;
if (!value) {
this.usernameError = 'Username is required';
}
if (value.length < 3) {
this.usernameError = 'Username must be at least 3 characters';
}
if (!/^[a-zA-Z0-9_]+$/.test(value)) {
this.usernameError = 'Username can only contain letters, numbers, and underscores';
}
}
FFV.setStrategyFor('username', validateUsername);With Parameters:
function validateMinLength(id, minLen) {
const value = this[`${id}Value`];
if (value.length < minLen) {
this[`${id}Error`] = `Must be at least ${minLen} characters`;
}
}
FFV.setStrategyFor('bio', validateMinLength, 'bio', 50);Specify where to show validation errors.
FFV.displayErrorsHere('error-container');Hide errors using visibility: hidden when valid.
FFV.onSuccess.hideFeedback();Hide errors using display: none when valid.
FFV.onSuccess.removeFeedback();Add a CSS class when validation succeeds.
FFV.onSuccess.addClass('valid-form');Remove a CSS class when validation succeeds.
FFV.onSuccess.removeClass('has-errors');Handle form submission after successful validation.
FFV.onSubmitButton('submit-btn', () => {
// Only called when form is valid
submitFormData();
});Start validation and attach event listeners.
const isValid = FFV.validate();
console.log(isValid); // true or false// Form 1
const loginForm = new FastFormValidator();
loginForm
.onEmail('login-email')
.onPassword('login-password')
.displayErrorsHere('login-errors')
.validate();
// Form 2
const signupForm = new FastFormValidator();
signupForm
.onEmail('signup-email')
.onPassword('signup-password', 10, 30)
.displayErrorsHere('signup-errors')
.validate();function validateConfirmPassword() {
const password = this.passwordValue;
const confirm = this.confirmPasswordValue;
if (password !== confirm) {
this.confirmPasswordError = 'Passwords do not match';
}
}
FFV.onPassword('password')
.setStrategyFor('confirmPassword', validateConfirmPassword)
.validate();function validateUsername() {
const username = this.usernameValue;
if (!username) {
this.usernameError = 'Username required';
return;
}
// Note: FFV validates synchronously, so handle async externally
// or use debouncing in your strategy
// Example with debouncing
clearTimeout(this.usernameTimeout);
this.usernameTimeout = setTimeout(async () => {
const available = await checkUsernameAvailability(username);
if (!available) {
this.usernameError = 'Username already taken';
this.validate(); // Re-trigger validation
}
}, 500);
}import { useEffect, useRef } from 'react';
import { FastFormValidator } from 'fast-form-validator';
function SignupForm() {
const validatorRef = useRef(null);
useEffect(() => {
validatorRef.current = new FastFormValidator();
validatorRef.current
.onEmail('email')
.onPassword('password', 8, 20)
.displayErrorsHere('errors')
.onSubmitButton('submit', handleSubmit)
.validate();
return () => {
validatorRef.current.destroy();
};
}, []);
const handleSubmit = () => {
console.log('Form submitted!');
};
return (
<form>
<input type="email" id="email" />
<input type="password" id="password" />
<button type="submit" id="submit">Sign Up</button>
<div id="errors"></div>
</form>
);
}FFV.onEmail('email')
.displayErrorsHere('errors')
.onSuccess.removeClass('error-visible')
.validate();#errors {
padding: 1rem;
border-radius: 4px;
margin-top: 1rem;
}
#errors.error-visible {
background: #fee;
border: 1px solid #c33;
color: #c33;
}
#errors:not(.error-visible) {
display: none;
}Breaking Changes:
- Multiple Instances: If you need multiple forms, use
new FastFormValidator()instead of the globalFFV
// Old (v1.x) - only one form per page
FFV.onEmail('email').validate();
// New (v2.x) - multiple forms supported
const form1 = new FastFormValidator();
form1.onEmail('email1').validate();
const form2 = new FastFormValidator();
form2.onEmail('email2').validate();
// Or keep using global FFV for single form
FFV.onEmail('email').validate();- Error Handling: Missing DOM elements now throw errors instead of console warnings
// Add error handling if elements might not exist
try {
FFV.displayErrorsHere('errors').validate();
} catch (error) {
console.error('Validation setup failed:', error);
}See Fast Form Validator in action: CodePen Demo
Contributions are welcome! Please read our Contributing Guide first.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
# Install dependencies
npm install
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Build for production
npm run build
# Run linter
npm run lintMIT ยฉ clickwithclark
- Inspired by the Strategy Pattern and fluent interfaces
- Built with โค๏ธ for the JavaScript community
- ๐ซ Open an issue
- ๐ฌ Discussions
- ๐ฆ Follow @clickwithclark
