nemo-validator
v1.2.1
Published
A comprehensive class-based form validation library with 25+ built-in validators, async validation support, and advanced features for web applications
Maintainers
Readme
Nemo Validator
A lightweight JavaScript class-based form validation library that helps validate different types of inputs in web forms at the event level.
Features
- Easy to set up and use with any HTML form
- Real-time validation with immediate feedback
- 🆕 Async validation support - API calls, database lookups, and external service validation
- Strict input filtering that blocks invalid characters at the keyboard event level
- Strict decimal place validation - prevents typing beyond 2 decimal places
- 25+ pre-built validation rules for common inputs (email, mobile, PAN, GST, URLs, dates, etc.)
- Advanced utility methods for programmatic validation and form management
- Field-level control - enable/disable validation for specific fields
- Custom error handling and form data extraction
- Promise-based validation with modern async/await patterns
- Loading states with custom messages during async validation
- Ability to add custom validation rules with event handling
- Pure JavaScript with no dependencies
- Lightweight and performance-optimized
Installation
Install the package using npm:
npm install nemo-validatorOr using yarn:
yarn add nemo-validatorBasic Usage
HTML
<!DOCTYPE html>
<html>
<head>
<title>Nemo Validator Example</title>
<style>
.text-danger {
color: red;
font-size: 0.8rem;
margin-top: 5px;
display: block;
}
</style>
</head>
<body>
<form class="nemo-validate-form">
<div>
<label for="name">Name:</label>
<input type="text" id="name" name="name" class="validate-name">
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" name="email" class="validate-email">
</div>
<div>
<label for="mobile">Mobile:</label>
<input type="text" id="mobile" name="mobile" class="validate-mobile">
</div>
<div>
<label for="amount">Amount:</label>
<input type="text" id="amount" name="amount" class="validate-two-decimal" placeholder="Enter amount (e.g., 123.45)">
<!-- Strictly blocks input after 2 decimal places -->
</div>
<button type="submit">Submit Form</button>
</form>
<script src="node_modules/nemo-validator/dist/index.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Initialize the validator
const validator = new NemoValidator('nemo-validate-form');
// Store validator instance for features
window.nemoValidatorInstance = validator;
// Validate form on submit
document.querySelector('.nemo-validate-form').addEventListener('submit', function(e) {
if (!validator.nemoValidateInputs()) {
e.preventDefault();
alert('Please fix the errors in the form.');
}
});
});
</script>
</body>
</html>ES Module Usage
import NemoValidator from 'nemo-validator';
document.addEventListener('DOMContentLoaded', function() {
// Initialize with default rules
const validator = new NemoValidator('nemo-validate-form');
// Store validator instance for features
window.nemoValidatorInstance = validator;
// Add a custom validation rule
validator.addRule('validate-password', {
pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/,
message: 'Password must be at least 8 characters, include uppercase, lowercase and a number.',
filterPattern: /[^\w!@#$%^&*()]/g
});
// Validate all inputs when form is submitted
document.querySelector('.nemo-validate-form').addEventListener('submit', function(e) {
if (!validator.nemoValidateInputs()) {
e.preventDefault();
console.log('Form has validation errors');
}
});
});Available Validation Rules
Core Validation Rules
| Rule Class | Validates | Description | |------------|-----------|-------------| | validate-name | Names | Letters, spaces, dots | | validate-mobile | Mobile numbers | 10-digit format | | validate-aadhar | Aadhar numbers | 12-digit format | | validate-pan | PAN card numbers | Format: ABCDE1234F | | validate-email | Email addresses | Standard email format | | validate-address | Addresses | Letters, numbers, spaces, dots, forward slash | | validate-pin | PIN codes | 6-digit format | | validate-text | Text | Letters, spaces, dots, forward slash | | validate-numeric | Numbers | Digits only | | validate-business | Business names | Letters, numbers, spaces, dots, forward slash | | validate-gst | GST numbers | Format: 22AAAAA0000A1Z5 | | validate-uam | UAM numbers | Format: DL05A1234567 | | validate-udyam | UDYAM numbers | Format: UDYAM-XX-00-0000000 | | validate-amount | Amounts | Strictly blocks typing beyond 2 decimal places at the event level | | validate-two-decimal | Amounts | Strictly blocks typing beyond 2 decimal places without using data attributes | | validate-strong-password | Passwords | Minimum 8 characters with uppercase, lowercase, number and special character | | validate-age | Age | Numbers between 18-100 with auto-constraints | | validate-credit-card | Credit Cards | Auto-formats with spaces after every 4 digits |
NEW: Extended Validation Rules
| Rule Class | Validates | Description | |------------|-----------|-------------| | validate-url | URLs | Web addresses with or without protocol | | validate-phone-international | International Phone | Format: +1234567890 | | validate-username | Usernames | 3-20 characters, letters, numbers, underscores | | validate-postal-code | Postal Codes | 3-10 alphanumeric characters | | validate-date-future | Future Dates | Dates that are in the future | | validate-date-past | Past Dates | Dates that are in the past | | validate-current-date | Current Date | Only today's date allowed | | validate-time | Time | 24-hour format (HH:MM) | | validate-color-hex | Hex Colors | Format: #FF0000 or #F00 | | validate-percentage | Percentage | 0-100 with up to 2 decimals | | validate-ip-address | IP Address | IPv4 format (192.168.1.1) | | validate-mac-address | MAC Address | Format: 00:1B:44:11:3A:B7 | | validate-slug | URL Slug | Lowercase letters, numbers, hyphens | | validate-currency | Currency | Multi-currency support with auto-formatting (default: Rs.) | | validate-social-security | SSN | Format: XXX-XX-XXXX | | validate-license-plate | License Plate | 1-8 alphanumeric characters |
Currency Validation (validate-currency)
The currency validation supports multiple international currencies with proper formatting and real-time validation. Each currency uses its native formatting conventions for thousand separators, decimal separators, and currency symbols.
How to Implement Currency Validation
Step 1: Add the CSS class to your input
<input type="text" class="validate-currency" name="amount" id="amount">Step 2: Specify currency format using data-currency attribute
<!-- For Euro -->
<input type="text" class="validate-currency" data-currency="EU" name="price" id="price">
<!-- For US Dollar -->
<input type="text" class="validate-currency" data-currency="US" name="salary" id="salary">Step 3: Initialize the validator
const validator = new NemoValidator('your-form-class');Supported Currency Formats
| Code | Currency | Symbol | Format Example | Decimal | Thousand | Grouping | |------|----------|--------|----------------|---------|----------|----------| | IN (default) | Indian Rupee | Rs. | Rs.12,34,567.89 | . | , | Indian | | INR | Indian Rupee | ₹ | ₹12,34,567.89 | . | , | Indian | | US | US Dollar | $ | $1,234,567.89 | . | , | Western | | USD | US Dollar | $ | $1,234,567.89 | . | , | Western | | EU | Euro | € | € 1.234.567,89 | , | . | Western | | EUR | Euro | € | € 1.234.567,89 | , | . | Western | | GB | British Pound | £ | £1,234,567.89 | . | , | Western | | GBP | British Pound | £ | £1,234,567.89 | . | , | Western | | JP | Japanese Yen | ¥ | ¥1,234,567.89 | . | , | Western | | JPY | Japanese Yen | ¥ | ¥1,234,567.89 | . | , | Western | | CN | Chinese Yuan | ¥ | ¥1,234,567.89 | . | , | Western | | CNY | Chinese Yuan | ¥ | ¥1,234,567.89 | . | , | Western | | RU | Russian Ruble | ₽ | ₽ 1 234 567,89 | , | space | Western | | RUB | Russian Ruble | ₽ | ₽ 1 234 567,89 | , | space | Western | | KR | Korean Won | ₩ | ₩1,234,567.89 | . | , | Western | | KRW | Korean Won | ₩ | ₩1,234,567.89 | . | , | Western |
Complete Implementation Examples
Basic Form with Multiple Currencies:
<form class="nemo-validate-form">
<!-- Default Indian Rupees (no data-currency needed) -->
<div>
<label for="price-inr">Price (Indian Rupees):</label>
<input type="text" id="price-inr" name="price-inr" class="validate-currency"
placeholder="Rs.12,34,567.89">
</div>
<!-- US Dollar -->
<div>
<label for="price-usd">Price (US Dollar):</label>
<input type="text" id="price-usd" name="price-usd" class="validate-currency"
data-currency="US" placeholder="$1,234,567.89">
</div>
<!-- Euro (uses comma as decimal separator) -->
<div>
<label for="price-eur">Price (Euro):</label>
<input type="text" id="price-eur" name="price-eur" class="validate-currency"
data-currency="EU" placeholder="€ 1.234.567,89">
</div>
<!-- British Pound -->
<div>
<label for="price-gbp">Price (British Pound):</label>
<input type="text" id="price-gbp" name="price-gbp" class="validate-currency"
data-currency="GB" placeholder="£1,234,567.89">
</div>
<button type="submit">Submit</button>
</form>
<script>
// Initialize validator
const validator = new NemoValidator('nemo-validate-form');
// Form submission with validation
document.querySelector('.nemo-validate-form').addEventListener('submit', function(e) {
e.preventDefault();
if (validator.nemoValidateInputs()) {
const formData = validator.getFormData();
console.log('Valid form data:', formData.formData);
// Process form submission
} else {
alert('Please fix the currency format errors.');
}
});
</script>Currency Format Behavior
Indian Grouping (IN, INR):
- Pattern: 12,34,567.89 (first group of 3, then groups of 2)
- Example: User types "1234567" → Displays "Rs.12,34,567"
Western Grouping (US, GB, JP, etc.):
- Pattern: 1,234,567.89 (groups of 3 digits)
- Example: User types "1234567" → Displays "$1,234,567"
European Format (EU, EUR):
- Pattern: 1.234.567,89 (dots for thousands, comma for decimal)
- Example: User types "1234567.89" → Displays "€ 1.234.567,89"
Russian Format (RU, RUB):
- Pattern: 1 234 567,89 (spaces for thousands, comma for decimal)
- Example: User types "1234567.89" → Displays "₽ 1 234 567,89"
Key Features
- 🔄 Real-time formatting: Automatically formats as user types
- 💱 Multi-currency support: 8+ major currencies with native formatting
- ✅ Dynamic validation: Each currency validates according to its format rules
- 🎯 Auto-detection: Can detect currency format from existing values
- 📱 User-friendly: Prevents invalid input and provides immediate feedback
- 🌍 Localized: Respects regional formatting conventions
- ⚡ Performance optimized: Efficient real-time processing
Important Notes
- Default Currency: If no
data-currencyattribute is specified, Indian Rupees (IN) format is used - Decimal Places: All currencies support up to 2 decimal places
- Auto-formatting: The library automatically adds currency symbols and formatting
- Validation: Each currency validates according to its specific format rules
- Error Messages: Dynamic error messages show the correct format example for each currency
Key Validation Behavior
Strict Decimal Place Validation
Nemo Validator implements strict decimal place validation that:
- Blocks typing beyond the decimal limit at the keydown event level
- Prevents invalid input directly during the typing process
- Handles all validation events (keydown, paste, input) to ensure completeness
- Preserves cursor position after formatting
Example usage (as shown in the example files):
<!-- For amounts with up to 2 decimal places -->
<input type="text" id="amount" name="amount" class="validate-two-decimal" placeholder="Enter amount (e.g., 123.45)">API Reference
Constructor
const validator = new NemoValidator(formClass, customRules);formClass: CSS class of the form(s) to validatecustomRules: (Optional) Object containing custom validation rules
Methods
init()
Initializes the validator on the specified forms.
nemoValidateInputs()
Validates all inputs in the form and returns a boolean indicating if all inputs are valid.
Example:
// Initialize the validator
const validator = new NemoValidator('nemo-validate-form');
// Validate on form submission
document.querySelector('.nemo-validate-form').addEventListener('submit', function(e) {
// Check if all inputs are valid
if (!validator.nemoValidateInputs()) {
// Prevent form submission if validation fails
e.preventDefault();
console.log('Form has validation errors');
} else {
console.log('All inputs are valid, proceeding with form submission');
// submit the form here
}
});validateField(element)
Validates a single input field and shows/hides error messages.
element: DOM element to validate
Example:
// Get a reference to the input element
const amountInput = document.getElementById('amount');
amountInput.addEventListener('blur', function() {
// Call the validator to check the field
const isValid = validator.validateField(this);
if (isValid) {
console.log('Amount field is valid');
} else {
console.log('Amount field has validation errors');
}
});addRule(name, rule)
Adds a custom validation rule.
name: Name of the rule (prefix 'validate-' optional)rule: Object containing the rule detailspattern: RegExp pattern to test againstmessage: Error message to displayfilterPattern: RegExp pattern to filter input (optional)maxLength: Maximum input length (optional)setupEvents: Function to set up custom event handlers (optional)customValidation: Function for custom validation logic (optional)
Example:
// Simplified custom rule that shows all available options
validator.addRule('my-decimal', {
// Basic validation pattern - allows exactly 2 decimal places
pattern: /^\d+\.\d{2}$/,
// Custom error message
message: 'Please enter a number with exactly 2 decimal places',
// Auto-filter out non-digits and extra dots
filterPattern: /[^\d.]/g,
// Maximum length constraint
maxLength: 10,
// Custom event handling
setupEvents: function(element) {
let lastValidValue = '';
const isValidInput = (value) => {
// Allow empty value or valid pattern
return !value || /^\d*\.?\d{0,2}$/.test(value);
};
element.addEventListener('keydown', function(e) {
// Allow navigation keys
if (e.key === 'Backspace' || e.key === 'Delete' ||
e.key === 'ArrowLeft' || e.key === 'ArrowRight' ||
e.key === 'Tab' || e.key === 'Home' || e.key === 'End' ||
e.ctrlKey || e.altKey || e.metaKey) {
return;
}
const newValue = this.value.substring(0, this.selectionStart) +
e.key +
this.value.substring(this.selectionEnd);
if (!isValidInput(newValue)) {
e.preventDefault();
}
});
element.addEventListener('input', function() {
if (isValidInput(this.value)) {
lastValidValue = this.value;
} else {
this.value = lastValidValue;
}
});
element.addEventListener('paste', function(e) {
const pastedText = (e.clipboardData || window.clipboardData).getData('text');
const newValue = this.value.substring(0, this.selectionStart) +
pastedText +
this.value.substring(this.selectionEnd);
if (!isValidInput(newValue)) {
e.preventDefault();
}
});
},
// Custom validation that runs during form validation
customValidation: function(value) {
if (!value) return false;
// Convert to number and check range
const num = parseFloat(value);
if (num < 0.01) {
this.message = 'Value must be at least 0.01';
return false;
}
if (num > 999.99) {
this.message = 'Value cannot exceed 999.99';
return false;
}
return true;
}
});
// Use this rule in HTML
// <input type="text" class="validate-my-decimal" placeholder="123.45">removeRule(name)
Removes a validation rule.
name: Name of the rule to remove
Example:
// Remove the built-in PAN validation rule
validator.removeRule('validate-pan');
// Or remove a custom rule
validator.removeRule('validate-indian-mobile');
console.log('The rule has been removed and will no longer be applied');getRules()
Gets all validation rules.
- Returns: Object containing all validation rules
Example:
// Get all current validation rules
const allRules = validator.getRules();
// Log rules to console
console.log('Available validation rules:', allRules);
// check if a specific rule exists
if (allRules['validate-email']) {
console.log('Email validation rule exists with pattern:', allRules['validate-email'].pattern);
}
// iterate through all rules
Object.keys(allRules).forEach(ruleName => {
console.log(`Rule: ${ruleName}, Message: ${allRules[ruleName].message}`);
});getRule(name)
Gets a specific validation rule.
name: Name of the rule to get (prefix 'validate-' optional)- Returns: Rule object or null if not found
Example:
// Get email validation rule
const emailRule = validator.getRule('email');
if (emailRule) {
console.log('Email pattern:', emailRule.pattern);
console.log('Email message:', emailRule.message);
}
// Check if rule exists
const customRule = validator.getRule('my-custom-rule');
if (!customRule) {
console.log('Custom rule not found');
}hasRule(name)
Checks if a validation rule exists.
name: Name of the rule to check (prefix 'validate-' optional)- Returns: Boolean indicating if rule exists
Example:
// Check if rules exist
if (validator.hasRule('email')) {
console.log('Email validation is available');
}
if (!validator.hasRule('custom-rule')) {
console.log('Need to add custom rule');
validator.addRule('custom-rule', {
pattern: /^custom$/,
message: 'Must be "custom"'
});
}validateValue(ruleName, value)
Validates a value against a specific rule without DOM interaction.
ruleName: Name of the rule to validate againstvalue: Value to validate- Returns: Object with
isValidandmessageproperties
Example:
// Validate email without DOM
const emailResult = validator.validateValue('email', '[email protected]');
if (emailResult.isValid) {
console.log('Email is valid');
} else {
console.log('Email error:', emailResult.message);
}
// Validate multiple values
const values = ['[email protected]', 'invalid-email', ''];
values.forEach(email => {
const result = validator.validateValue('email', email);
console.log(`${email}: ${result.isValid ? 'Valid' : result.message}`);
});
// Use in custom logic
function checkEmailAvailability(email) {
const validation = validator.validateValue('email', email);
if (!validation.isValid) {
return { available: false, error: validation.message };
}
// Proceed with availability check...
return { available: true };
}getValidationErrors()
Gets validation errors for all fields in the form.
- Returns: Array of error objects with field, element, rule, message, and value properties
Example:
// Get all validation errors
const errors = validator.getValidationErrors();
if (errors.length > 0) {
console.log('Form has errors:');
errors.forEach(error => {
console.log(`Field: ${error.field}, Error: ${error.message}`);
});
// Focus on first error field
errors[0].element.focus();
} else {
console.log('Form is valid');
}
// Use in form submission
document.querySelector('form').addEventListener('submit', function(e) {
const errors = validator.getValidationErrors();
if (errors.length > 0) {
e.preventDefault();
// Show summary of errors
const errorSummary = errors.map(err => `${err.field}: ${err.message}`).join('\n');
alert('Please fix the following errors:\n' + errorSummary);
}
});clearValidationErrors()
Clears all validation errors and styling.
- Returns: Validator instance for method chaining
Example:
// Clear all errors
validator.clearValidationErrors();
// Chain with other methods
validator
.clearValidationErrors()
.toggleFieldValidation(['email', 'phone'], false)
.setFieldError('username', 'Username is required');
// Use in form reset
document.querySelector('#resetBtn').addEventListener('click', function() {
document.querySelector('form').reset();
validator.clearValidationErrors();
});toggleFieldValidation(fieldNames, enabled)
Enables or disables validation for specific fields.
fieldNames: Field name(s) to enable/disable (string or array)enabled: Whether to enable (true) or disable (false) validation- Returns: Validator instance for method chaining
Example:
// Disable validation for specific fields
validator.toggleFieldValidation('email', false);
validator.toggleFieldValidation(['phone', 'address'], false);
// Re-enable validation
validator.toggleFieldValidation('email', true);
// Conditional validation based on user type
const userType = document.querySelector('#userType').value;
if (userType === 'guest') {
validator.toggleFieldValidation(['phone', 'address'], false);
} else {
validator.toggleFieldValidation(['phone', 'address'], true);
}
// Chain operations
validator
.clearValidationErrors()
.toggleFieldValidation('optionalField', false);setFieldError(fieldName, message)
Sets a custom error message for a specific field.
fieldName: Field name or IDmessage: Custom error message (empty string to clear)- Returns: Validator instance for method chaining
Example:
// Set custom error
validator.setFieldError('username', 'Username is already taken');
// Clear specific error
validator.setFieldError('username', '');
// Use with server-side validation
async function checkUsernameAvailability(username) {
try {
const response = await fetch('/check-username', {
method: 'POST',
body: JSON.stringify({ username }),
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
if (!result.available) {
validator.setFieldError('username', 'Username is not available');
return false;
} else {
validator.setFieldError('username', ''); // Clear error
return true;
}
} catch (error) {
validator.setFieldError('username', 'Error checking username availability');
return false;
}
}
// Use in real-time checking
document.querySelector('#username').addEventListener('blur', async function() {
if (this.value) {
await checkUsernameAvailability(this.value);
}
});getFormData()
Gets form data with validation status.
- Returns: Object containing
formData,isValid, anderrorsproperties
Example:
// Get form data with validation
const result = validator.getFormData();
console.log('Form data:', result.formData);
console.log('Is valid:', result.isValid);
console.log('Errors:', result.errors);
// Use in form submission
document.querySelector('form').addEventListener('submit', function(e) {
e.preventDefault();
const result = validator.getFormData();
if (result.isValid) {
// Submit data
console.log('Submitting:', result.formData);
// Example: Send to server
fetch('/submit-form', {
method: 'POST',
body: JSON.stringify(result.formData),
headers: { 'Content-Type': 'application/json' }
});
} else {
console.log('Form has errors:', result.errors);
// Focus first error field
if (result.errors.length > 0) {
result.errors[0].element.focus();
}
}
});
// Use for auto-save functionality
setInterval(() => {
const result = validator.getFormData();
if (result.isValid && Object.keys(result.formData).length > 0) {
// Auto-save valid form data
localStorage.setItem('formDraft', JSON.stringify(result.formData));
}
}, 30000); // Auto-save every 30 secondsAsync Validation
Nemo Validator supports asynchronous validation for scenarios requiring API calls, database lookups, or other async operations.
Creating Async Validation Rules
First, set up your HTML with the CSS class that matches your rule name:
<form class="nemo-validate-form">
<div>
<label for="username">Username:</label>
<!-- The class 'validate-async-username' connects to the rule 'async-username' -->
<input type="text" id="username" name="username" class="validate-async-username"
placeholder="Enter username to check availability">
</div>
<div>
<label for="email">Email:</label>
<!-- The class 'validate-async-email' connects to the rule 'async-email' -->
<input type="email" id="email" name="email" class="validate-async-email"
placeholder="Enter email for domain validation">
</div>
<button type="submit">Submit Form</button>
</form>Then create the corresponding async validation rules in JavaScript:
// Initialize validator
const validator = new NemoValidator('nemo-validate-form');
// Add async validation rule for username
// Rule name 'async-username' matches CSS class 'validate-async-username'
validator.addRule('async-username', {
message: 'Username is not available',
loadingMessage: 'Checking username availability...',
errorMessage: 'Unable to check username availability. Please try again.',
asyncValidation: async function(value) {
// Simulate API call
const response = await fetch(`/api/check-username/${value}`);
const result = await response.json();
// Return boolean for simple validation
return result.available;
// Or return detailed result object
return {
isValid: result.available,
message: result.available ? 'Username is available!' : `Username "${value}" is already taken`
};
}
});
// Add async validation rule for email domain
// Rule name 'async-email' matches CSS class 'validate-async-email'
validator.addRule('async-email', {
message: 'Email domain is not accessible',
loadingMessage: 'Validating email domain...',
errorMessage: 'Unable to validate email domain. Please try again.',
asyncValidation: async function(value) {
// Basic email format check first
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailPattern.test(value)) {
return { isValid: false, message: 'Please enter a valid email format' };
}
// Simulate domain validation API call
const domain = value.split('@')[1];
const response = await fetch(`/api/validate-domain/${domain}`);
const result = await response.json();
return {
isValid: result.isValid,
message: result.isValid ? 'Email domain is valid' : `Domain "${domain}" is not accessible`
};
}
});How CSS Classes Connect to Rules:
- CSS class
validate-async-username→ Rule nameasync-username - CSS class
validate-async-email→ Rule nameasync-email - The library automatically adds the
validate-prefix when looking for CSS classes
Async Validation Methods
validateValueAsync(ruleName, value)
Validates a value asynchronously against a specific rule.
// Async validation
const result = await validator.validateValueAsync('async-username', 'john_doe');
console.log(result.isValid); // true/false
console.log(result.message); // Custom messagevalidateInputsAsync()
Validates all form inputs asynchronously.
// Validate all inputs including async rules
const isValid = await validator.validateInputsAsync();
if (isValid) {
console.log('All validations passed!');
}getValidationErrorsAsync()
Gets all validation errors including async validations.
const errors = await validator.getValidationErrorsAsync();
errors.forEach(error => {
console.log(`${error.field}: ${error.message}`);
});getFormDataAsync()
Gets form data with async validation status.
const result = await validator.getFormDataAsync();
console.log('Form Data:', result.formData);
console.log('Is Valid:', result.isValid);
console.log('Errors:', result.errors);Async Validation Features
- Loading States: Show custom loading messages during validation
- Error Handling: Graceful error handling with custom error messages
- Promise-based: Full Promise support for modern async/await patterns
- Mixed Validation: Seamlessly mix sync and async validations
- Custom Messages: Detailed validation results with custom success/error messages
Example: Form Submission with Async Validation
document.querySelector('form').addEventListener('submit', async function(e) {
e.preventDefault();
try {
const result = await validator.getFormDataAsync();
if (result.isValid) {
// Submit form data
await submitForm(result.formData);
alert('Form submitted successfully!');
} else {
// Show validation errors
result.errors.forEach(error => {
console.log(`${error.field}: ${error.message}`);
});
}
} catch (error) {
console.error('Validation failed:', error);
}
});Creating Custom Rules with Event Validation
// Custom rule with decimal validation
const myCustomRules = {
'validate-custom-decimal': {
pattern: /^[0-9]+(\.[0-9]{0,2})?$/,
message: 'Please enter a valid number with up to 2 decimal places',
filterPattern: /[^0-9.]/g,
setupEvents: function(element) {
// Setup custom event handlers
element.addEventListener('keydown', function(e) {
// Custom logic here
});
element.addEventListener('input', function() {
// Custom input handling
});
}
}
};
// Initialize with custom rules
const validator = new NemoValidator('my-form', myCustomRules);Browser Compatibility
Nemo Validator works in all modern browsers:
- Chrome, Firefox, Safari, Edge (latest versions)
- IE11 with appropriate polyfills
License
MIT
