shadow-form-handler
v2.0.1
Published
v2.0.1 is a powerful and flexible form-handling and validation library for JavaScript and TypeScript. It simplifies the process of creating and managing complex forms by providing a rich set of features, an intuitive API, and an extensible architecture. W
Downloads
3
Readme
shadow-form-handler
Overview
shadow-form-handler is a powerful and flexible form-handling and validation library for JavaScript and TypeScript. It simplifies the process of creating and managing complex forms by providing a rich set of features, an intuitive API, and an extensible architecture. Whether you’re building simple forms or complex multi-step workflows, shadow-form-handler has you covered with robust validation, dynamic field management, and seamless integration capabilities.
🚀 Key Features
Dynamic Field Management:
- Easily add, remove, and modify form fields at runtime.
- Specify the position where new fields should be inserted (top, bottom, or a specific index).
- Disable buttons when adding or removing fields for a better user experience.
Flexible Validation:
- Leverage both schema-based and custom validation rules.
- Utilize built-in validation rules like
required
,minLength
,maxLength
,pattern
,email
,range
, andmatches
. - Create custom validation rules with asynchronous support.
- Set up validations that depend on the values of other fields.
Error Handling:
- Display error messages for invalid fields with customizable styling.
- Provide clear and specific error messages to enhance the user experience.
- Automatically display errors when validation fails.
Event Management:
- Attach custom event listeners to form fields (e.g.,
input
,change
,blur
). - Integrate with form events like
onFormSubmitSuccess
,onFormSubmitFail
, andonFieldValidationError
.
- Attach custom event listeners to form fields (e.g.,
Hooks System:
- Extend the functionality of the form handler by adding custom hooks.
- Trigger hooks at various stages of the form lifecycle, such as field registration, validation, and submission.
- Use hooks to implement custom logic, logging, or side effects.
Validation Modes:
- Choose between
default
(on form submit) andruntime
(real-time) validation modes. - Automatically add runtime validation to new fields when they are registered.
- Choose between
Asynchronous Validation:
- Perform asynchronous validations with ease, such as checking for uniqueness on the server.
- Implement timeout handling to ensure a smooth user experience.
Dependent Field Validation:
- Set up validations that depend on the values of other form fields.
- Automatically re-validate dependent fields when their dependencies change.
Internationalization and Localization:
- Provide translations for validation error messages.
- Support multiple languages to reach a global audience.
- Easily add new translations or override existing ones.
🎯 Benefits
- Reduced Development Time: Streamline form creation and validation with minimal boilerplate code.
- Enhanced User Experience: Provide instant feedback with real-time validation and clear error messages.
- Flexibility: Easily adapt to changing requirements with dynamic field management and extensible architecture.
- Powerful Validation: Combine schema-based and custom validators to handle complex validation scenarios.
- Asynchronous Support: Seamlessly integrate server-side validations without blocking the UI.
- Event-Driven Architecture: Extend functionality with hooks and custom event listeners.
- Customizable UI: Tailor error messages and styles to match your application's design.
- Internationalization: Support multiple languages for a global reach.
📦 Installation
Using npm
Install the package via npm:
npm install shadow-form-handler
Using HTML Script Tag
To use ShadowFormHandler directly in your HTML file, add the following script tag:
<script src="./node_modules/shadow-form-handler/dist/shadow-form-handler.js"></script>
Using CDN
Alternatively, you can use ShadowFormHandler via a CDN by adding this script tag:
<script src="https://cdn.jsdelivr.net/gh/Mostafashadow1/[email protected]/dist/shadow-form-handler.js"></script>
Using GitHub Releases
You can also download the latest release directly from GitHub. Follow these steps:
Navigate to the Releases Page: Go to the Releases section of your GitHub repository.
Download the Latest Release: Find the latest release and download the
shadow-form-handler.js
file from the assets section.Include the Script in Your HTML: Add the downloaded file to your project and include it in your HTML file like this:
<script src="path/to/shadow-form-handler.js"></script>
Simple Form Handling
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simple Example with shadow-form-handler</title>
<link rel="stylesheet" href="./styles.css">
</head>
<body>
<form id="myForm">
<div>
<label for="username">Username:</label>
<input type="text" id="username" >
<span id="username-error" class="error-message"></span>
</div>
<button type="submit">Submit</button>
</form>
<script src="https://cdn.jsdelivr.net/gh/Mostafashadow1/[email protected]/dist/shadow-form-handler.js"></script>
<script src="./index.js"></script>
</body>
</html>
const { FormHandler } = shadowFormHandler;
const formHandler = new FormHandler();
// Register a field
formHandler.register({
id: 'username',
initialValue: "",
schemaValidation: [
formHandler.validation.required(), // if no message ? show default message
formHandler.validation.minLength(3, 'Username must be at least 3 characters long'),
formHandler.validation.maxLength(15, 'Username must be less than 15 characters'),
]
});
// Set up form submission
formHandler.submitHandler('myForm', (values) => {
console.log('Form submitted with values:', values);
});
Core Components
Methods
Form Field Methods
register({id: string, initialValue?: string, schemaValidation?: [], customValidation?:[] })
:- Purpose: Register a new form field.
- Usage:
formHandler.register({ id: 'username', initialValue: '', schemaValidation: [], customValidation: [] });
setMode(newMode: 'default' || 'runtime')
:- Purpose: Set the validation mode (e.g., Default, Runtime).
- Usage:
formHandler.setMode('runtime');
submitHandler(formId: string, onSubmit?: Function)
:- Purpose: Handle form submission.
- Usage:
formHandler.submitHandler('myForm', (data) => console.log(data));
getValue(id: string)
:- Purpose: Get the value of a specific field.
- Usage:
const username = formHandler.getValue('username');
getValues()
:- Purpose: Get values of all fields.
- Usage:
const allValues = formHandler.getValues();
resetForm()
:- Purpose: Reset all form fields and errors.
- Usage:
formHandler.resetForm();
removeField({ fieldId: string, disabledId?: string })
:- Purpose: Remove a field dynamically.
- Usage:
formHandler.removeField({ fieldId: 'descraption'});
addField({containerId: string, fieldId: string, labelText: string, register?: RegisterParams, position?: "top" | "bottom" | number, disabledId?: string })
:- Purpose: Add a new field dynamically.
- Usage:
formHandler.addField({ containerId: 'formContainer', fieldId: 'password', labelText: 'Password', register: { id: 'password', validation: 'required|min:8' }, position: 'bottom' });
setErrorStyles(style: ErrorStyle)
:- Purpose: Set custom error styles.
- Usage:
formHandler.setErrorStyles({ color: 'red', fontSize: '12px' });
Sure! Here's the updated section for your README file:
Methods
addHooks(hooks: Hooks)
Purpose: Add custom hooks for form lifecycle events. Usage:
formHandler.addHooks({
onFormSubmitSuccess: (values) => {
console.log("Form submitted successfully with values:", values);
},
onFormSubmitFail: (errors) => {
console.error("Form submission failed with errors:", errors);
},
onFieldValidationError: (fieldId, error) => {
if (error) {
console.warn(`Validation error on field ${fieldId}: ${error}`);
}
},
onFormReset: () => {
console.log("Form reset successfully");
},
beforeFieldRegister: (fieldId, params) => {
console.log(`Registering field: ${fieldId}`, params);
},
afterFieldRegister: (fieldId, params) => {
console.log(`Field registered: ${fieldId}`, params);
},
onValidationStart: (fields) => {
console.log("Validation started", fields);
},
onValidationEnd: (fields) => {
console.log("Validation ended", fields);
},
onValueChange: (fieldId, value) => {
console.log(fieldId, value);
},
onFieldAdd: (fieldId) => {
console.log(fieldId);
},
onFieldRemove: (fieldId) => {
console.log(fieldId);
},
onFocus: (field) => {
console.log(field);
},
onBlur: (field) => {
console.log(field);
},
});
addCustomEventListener(id: string, event: string, listener: EventListener)
:- Purpose: Add a custom event listener to a field.
- Usage:
formHandler.addCustomEventListener('username', 'focus', () => console.log('Username field focused'));
Language Methods
setCurrentLanguage(langCode: string)
:- Purpose: Set the current language.
- Usage:
formHandler.lang.setCurrentLanguage('ar');
getCurrentLanguage()
:- Purpose: Get the current language.
- Usage:
const currentLang = formHandler.lang.getCurrentLanguage();
addTranslations(lang: string, translations: { [key: string]: string; })
:- Purpose: Add translations for a specific language.
- Usage:
formHandler.lang.addTranslations('en', { 'password': 'Password must contain at least one uppercase letter, one lowercase letter, and one number.', 'confirmPassword' : "Passwords do not match" }); formHandler.lang.addTranslations('ar', { 'password': 'يجب أن تحتوي كلمة المرور على حرف كبير واحد على الأقل، وحرف صغير واحد، ورقم واحد.', 'confirmPassword' : "كلمات المرور غير متطابقة." }); formHandler.lang.addTranslations('es', { 'password': 'Le mot de passe doit contenir au moins une lettre majuscule, une lettre minuscule et un chiffre.', 'confirmPassword' : "Les mots de passe ne correspondent pas." });
const currentLang = formHandler.lang.getCurrentLanguage();
Built-in Validation Rules
The package provides the following validation rules:
required(message?: string)
:- Ensures the field is not empty.
- If no
message
is provided, it will use the translation for the 'required' key, or the default message"This field is required."
.
minLength(min: number, message?: string)
:- Checks if the value has at least the minimum length.
- If no
message
is provided, it will use the translation for the 'minLength' key, or the default message"This field must be at least {min} characters long."
.
maxLength(max: number, message?: string)
:- Checks if the value doesn't exceed the maximum length.
- If no
message
is provided, it will use the translation for the 'maxLength' key, or the default message"This field must be no more than {max} characters long."
.
pattern(regex: RegExp, message?: string)
:- Validates the value against a regular expression pattern.
- If no
message
is provided, it will use the translation for the 'pattern' key, or the default message"This field does not match the required pattern."
.
email(message?: string)
:- Checks if the value is a valid email format.
- If no
message
is provided, it will use the translation for the 'email' key, or the default message"This field must be a valid email address."
.
range(min: number, max: number, message?: string)
:- Ensures the value is within a specified range.
- If no
message
is provided, it will use the translation for the 'range' key, or the default message"The value must be between {min} and {max}."
.
matches(fieldToMatch: string, message?: string)
:- Ensures the value matches another field's value.
- If no
message
is provided, it will use the translation for the 'matches' key, or the default message"This field must match the {fieldToMatch} field."
.
The validation rules use the lang.getTranslation()
function to retrieve the appropriate error message. If the translation key is not found, the default message will be used.
Dynamic Field Management
// Add a new field
formHandler.addField({
containerId: 'formContainer',
fieldId: 'newField',
labelText: 'New Field',
register: {
initialValue: '',
schemaValidation: [required('This field is required')]
},
position: 'top' // position of element added: 'top' | 'bottom' | number of element filed like 3
});
// Remove a field
formHandler.removeField({
fieldId: 'fieldToRemove',
disabledId: 'addButton'
});
Asynchronous Validation
formHandler.register({
id: 'username',
customValidation: [{
validate: async (value) => {
// Simulating an API call to check username uniqueness
await new Promise(resolve => setTimeout(resolve, 1000));
return !value.includes('shadow' && 'mostafa mohamed' && 'mostafa');
},
message: 'This username is already taken.',
}]
});
Internationalization and Localization
// Set the current language
formHandler.lang.setCurrentLanguage('ar');
// Add translations for different languages
formHandler.lang.addTranslations('en', {
'required': 'This field is required.',
'minLength': 'This field must be at least {min} characters long.',
'maxLength': 'This field must not exceed {max} characters.',
'email': 'Please enter a valid email address.',
'range': 'Value must be between {min} and {max}.',
'matches': 'This field must match {fieldToMatch}.',
});
formHandler.lang.addTranslations('ar', {
'required': 'هذا الحقل مطلوب.',
'minLength': 'يجب أن يحتوي هذا الحقل على {min} أحرف على الأقل.',
'maxLength': 'يجب ألا يتجاوز هذا الحقل {max} حرفًا.',
'email': 'يرجى إدخال عنوان بريد إلكتروني صالح.',
'range': 'يجب أن تكون القيمة بين {min} و {max}.',
'matches': 'يجب أن يتطابق هذا الحقل مع {fieldToMatch}.',
});
Dependent Field Validation With built in 'matches' method
formHandler.lang.addTranslations('en', {
'password': 'Password must contain at least one uppercase letter, one lowercase letter, and one number.',
'confirmPassword' : "Passwords do not match"
});
formHandler.lang.addTranslations('ar', {
'password': 'يجب أن تحتوي كلمة المرور على حرف كبير واحد على الأقل، وحرف صغير واحد، ورقم واحد.',
'confirmPassword' : "كلمات المرور غير متطابقة."
});
formHandler.lang.addTranslations('es', {
'password': 'Le mot de passe doit contenir au moins une lettre majuscule, une lettre minuscule et un chiffre.',
'confirmPassword' : "Les mots de passe ne correspondent pas."
});
formHandler.register({
id: 'password',
schemaValidation: [
formHandler.validation.required(),
formHandler.validation.minLength(8),
formHandler.validation.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/, formHandler.lang.getTranslation('password'))
]
});
formHandler.register({
id: 'confirm-password',
schemaValidation: [
formHandler.validation.required(),
formHandler.validation.matches('password' , formHandler.lang.getTranslation('confirmPassword'))
]
});
in this approach we prefer uses dependencies
formHandler.register({
id: 'confirm-password',
dependencies: ['password'],
customValidation: [{
validate: (value, formValues) => value === formValues.password,
message: formHandler.lang.getTranslation('confirmPassword')
}]
});
Hooks System
onFormSubmitSuccess(values)
: Triggered when the form is successfully submitted.- Parameters:
values
: The values submitted in the form.
- Example:
onFormSubmitSuccess: (values) => { console.log("Form submitted successfully with values:", values); }
- Parameters:
onFormSubmitFail(errors)
: Triggered when the form submission fails.- Parameters:
errors
: The errors encountered during submission.
- Example:
onFormSubmitFail: (errors) => { console.error("Form submission failed with errors:", errors); }
- Parameters:
onFieldValidationError(fieldId, error)
: Triggered when a field validation error occurs.- Parameters:
fieldId
: The ID of the field with the error.error
: The validation error message.
- Example:
onFieldValidationError: (fieldId, error) => { if (error) { console.warn(`Validation error on field ${fieldId}: ${error}`); } }
- Parameters:
onFormReset()
: Triggered when the form is reset.- Example:
onFormReset: () => { console.log("Form reset successfully"); }
- Example:
beforeFieldRegister(fieldId, params)
: Triggered before a field is registered.- Parameters:
fieldId
: The ID of the field being registered.params
: The parameters for the field registration.
- Example:
beforeFieldRegister: (fieldId, params) => { console.log(`Registering field: ${fieldId}`, params); }
- Parameters:
afterFieldRegister(fieldId, params)
: Triggered after a field is registered.- Parameters:
fieldId
: The ID of the field being registered.params
: The parameters for the field registration.
- Example:
afterFieldRegister: (fieldId, params) => { console.log(`Field registered: ${fieldId}`, params); }
- Parameters:
onValidationStart(fields)
: Triggered when validation starts.- Parameters:
fields
: The fields being validated.
- Example:
onValidationStart: (fields) => { console.log("Validation started", fields); }
- Parameters:
onValidationEnd(fields)
: Triggered when validation ends.- Parameters:
fields
: The fields that were validated.
- Example:
onValidationEnd: (fields) => { console.log("Validation ended", fields); }
- Parameters:
onValueChange(fieldId, value)
: Triggered when a field value changes.- Parameters:
fieldId
: The ID of the field.value
: The new value of the field.
- Example:
onValueChange: (fieldId, value) => { console.log(fieldId, value); }
- Parameters:
onFieldAdd(fieldId)
: Triggered when a field is added.- Parameters:
fieldId
: The ID of the field being added.
- Example:
onFieldAdd: (fieldId) => { console.log(fieldId); }
- Parameters:
onFieldRemove(fieldId)
: Triggered when a field is removed.- Parameters:
fieldId
: The ID of the field being removed.
- Example:
onFieldRemove: (fieldId) => { console.log(fieldId); }
- Parameters:
onFocus(field)
: Triggered when a field gains focus.- Parameters:
field
: The field that gained focus.
- Example:
onFocus: (field) => { console.log(field); }
- Parameters:
onBlur(field)
: Triggered when a field loses focus.- Parameters:
field
: The field that lost focus.
- Example:
onBlur: (field) => { console.log(field); }
- Parameters:
💡 Usage Example
Here's a comprehensive example demonstrating the power of shadow-form-handler:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Enhanced Form Validation Example</title>
<link rel="stylesheet" href="./styles.css">
</head>
<body>
<form id="myForm">
<div>
<label for="firstname">Firstname:</label>
<input type="text" id="firstname" >
<span id="firstname-error" class="error-message"></span>
</div>
<div>
<label for="lastname">Lastname:</label>
<input type="text" id="lastname" >
<span id="lastname-error" class="error-message"></span>
</div>
<div>
<label for="age">Age:</label>
<input type="number" id="age" >
<span id="age-error" class="error-message"></span>
</div>
<div>
<label for="username">Username:</label>
<input type="text" id="username" >
<span id="username-error" class="error-message"></span>
</div>
<div>
<label for="email">Email:</label>
<input type="text" id="email" >
<span id="email-error" class="error-message"></span>
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" >
<span id="password-error" class="error-message"></span>
</div>
<div>
<label for="confirm-password">Confirm Password:</label>
<input type="password" id="confirm-password" >
<span id="confirm-password-error" class="error-message"></span>
</div>
<button type="submit">Submit</button>
<button type="button" id="removeUsername">Remove Username Field</button>
<button type="button" id="addDescription">Add Description Field</button>
<button type="button" id="resetform">Reset Form</button>
</form>
<script src="https://cdn.jsdelivr.net/gh/Mostafashadow1/[email protected]/dist/shadow-form-handler.js"></script>
<script src="./index.js"></script>
</body>
</html>
const { FormHandler} = shadowFormHandler;
const formHandler = new FormHandler();
formHandler.setMode('runtime'); // runtime or default
formHandler.lang.getCurrentLanguage();
// Add translations
formHandler.lang.addTranslations('en', {
'required': 'This field is required.',
'minLength': 'This field must be at least {min} characters long.',
'maxLength': 'This field must not exceed {max} characters.',
'email': 'Please enter a valid email address.',
'range': 'Value must be between {min} and {max}.',
'matches': 'This field must match {fieldToMatch}.',
});
formHandler.lang.addTranslations('ar', {
'required': 'هذا الحقل مطلوب.',
'minLength': 'يجب أن يحتوي هذا الحقل على {min} أحرف على الأقل.',
'maxLength': 'يجب ألا يتجاوز هذا الحقل {max} حرفًا.',
'email': 'يرجى إدخال عنوان بريد إلكتروني صالح.',
'range': 'يجب أن تكون القيمة بين {min} و {max}.',
'matches': 'يجب أن يتطابق هذا الحقل مع {fieldToMatch}.',
});
formHandler.lang.addTranslations('es', {
'required': 'Este campo es obligatorio.',
'minLength': 'Este campo debe tener al menos {min} caracteres.',
'maxLength': 'Este campo no debe exceder los {max} caracteres.',
'email': 'Por favor, introduce una dirección de correo electrónico válida.',
'range': 'El valor debe estar entre {min} y {max}.',
'matches': 'Este campo debe coincidir con {fieldToMatch}.',
});
formHandler.lang.setCurrentLanguage('ar')
formHandler.setErrorStyles({
color: "red",
marginTop:2,
})
formHandler.register({
id: "firstname",
initialValue: "",
schemaValidation: [
formHandler.validation.required(),
formHandler.validation.maxLength(10),
formHandler.validation.minLength(4)
]
});
formHandler.register({
id: "lastname",
initialValue: "",
schemaValidation: [
formHandler.validation.required(),
formHandler.validation.maxLength(10),
formHandler.validation.minLength(4)
]
});
formHandler.lang.addTranslations('en', {
'usernameTaken': 'This username is already taken.'
});
formHandler.lang.addTranslations('ar', {
'usernameTaken': 'اسم المستخدم هذا مستخدم بالفعل.'
});
formHandler.lang.addTranslations('es', {
'usernameTaken': 'Este nombre de usuario ya está en uso.'
});
formHandler.register({
id: "username",
dependencies: ['email'],
schemaValidation: [formHandler.validation.required() , formHandler.validation.minLength(3),
formHandler.validation.maxLength(20)],
customValidation: [
{
validate: async (value) => {
// Simulate an API call to check if the email is already registered
await new Promise(resolve => setTimeout(resolve, 1000));
return !value.includes('shadow' && 'mostafa mohamed' && 'mostafa');
},
message: formHandler.lang.getTranslation('usernameTaken'),
}
]
});
formHandler.register({
id: 'email',
schemaValidation: [
formHandler.validation.required(),
formHandler.validation.email()
]
});
formHandler.lang.addTranslations('en', {
'password': 'Password must contain at least one uppercase letter, one lowercase letter, and one number.',
'confirmPassword' : "Passwords do not match"
});
formHandler.lang.addTranslations('ar', {
'password': 'يجب أن تحتوي كلمة المرور على حرف كبير واحد على الأقل، وحرف صغير واحد، ورقم واحد.',
'confirmPassword' : "كلمات المرور غير متطابقة."
});
formHandler.lang.addTranslations('es', {
'password': 'Le mot de passe doit contenir au moins une lettre majuscule, une lettre minuscule et un chiffre.',
'confirmPassword' : "Les mots de passe ne correspondent pas."
});
formHandler.register({
id: 'password',
schemaValidation: [
formHandler.validation.required(),
formHandler.validation.minLength(8),
formHandler.validation.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/, formHandler.lang.getTranslation('password'))
]
});
formHandler.register({
id: 'confirm-password',
schemaValidation: [
formHandler.validation.required(),
formHandler.validation.matches('password' , formHandler.lang.getTranslation('confirmPassword'))
]
});
formHandler.register({
id: 'confirm-password',
dependencies: ['password'],
customValidation: [{
validate: (value, formValues) => value === formValues.password,
message: formHandler.lang.getTranslation('confirmPassword')
}]
});
formHandler.register({
id: 'age',
schemaValidation: [
formHandler.validation.required(),
formHandler.validation.range(18, 100)
]
});
// Adding hooks for validation events
formHandler.addHooks({
onFormSubmitSuccess: (values) => {
console.log("Form submitted successfully with values:", values);
},
onFormSubmitFail: (errors) => {
console.error("Form submission failed with errors:", errors);
},
onFieldValidationError: (fieldId, error) => {
if(error) {
console.warn(`Validation error on field ${fieldId}: ${error}`);
}
},
onFormReset: () => {
console.log(`form reseted susccfully`);
},
beforeFieldRegister: (fieldId, params) => {
console.log(`Registering field: ${fieldId}`, params);
},
afterFieldRegister: (fieldId, params) => {
console.log(`Field registered: ${fieldId}`, params);
},
onValidationStart: (fields) => {
console.log( "beforeValidate", fields),
},
onValidationEnd:(fields) => {
console.log("after validated" , fields)
},
onValueChange: (fieldId, value) => {
console.log(fieldId , value)
},
onFieldAdd:(fieldId) => {
console.log(fieldId)
},
onFieldRemove:(fieldId) => {
console.log(fieldId)
},
onFocus:(field) => {
console.log(field)
},
onBlur:(field) => {
console.log(field)
},
})
// Adding custom event listener
formHandler.addCustomEventListener("email", "blur", (event) => {
console.log("Email input lost focus", event);
});
// Handling form submission
formHandler.submitHandler('myForm', (values) => {
console.log('Form submitted with values:', values);
});
// Adding a field dynamically
document.getElementById('addDescription').addEventListener('click', () => {
formHandler.addField({
containerId:'myForm',
fieldId:'description',
labelText:'Description',
register:{
initialValue:'',
schemaValidation:[formHandler.validation.required()],
},
position:3,
disabledId:"addDescription",
register:{
initialValue: "",
schemaValidation: [
formHandler.validation.required(),
formHandler.validation.maxLength(10),
formHandler.validation.minLength(4)
],
customValidation:[]
}
})
});
// Removing a field dynamically
document.getElementById('removeUsername').addEventListener('click', () => {
formHandler.removeField( {fieldId : "username" , disabledId:"removeUsername"} );
});
// Removing a field dynamically
document.getElementById('resetform').addEventListener('click', () => {
formHandler.resetForm()
});
🛠️ Best Practices
- Clear Error Messages: Provide clear and specific error messages for each validation rule to enhance the user's understanding.
- Asynchronous Validations: Use asynchronous validations sparingly to avoid performance issues. Ensure they are necessary and optimized.
- Error Handling: Implement proper error handling for asynchronous operations to manage potential issues gracefully.
- Utilize Hooks: Leverage hooks to extend functionality without modifying the core logic, ensuring maintainability and flexibility.
- Regular Resets: Regularly reset the form to clear old data and errors, maintaining a fresh state for new submissions.
🔧 Troubleshooting
- Validation Issues: If fields are not being validated, ensure they are properly registered with the correct validation rules.
- Runtime Validation: For runtime validation issues, verify that the correct mode (
default
orruntime
) is set. - Event Listeners: If custom event listeners are not firing, check the element IDs and event types to ensure they are correctly specified.
🤝 Contributing
Contributions to the shadow-form-handler
package are welcome! Please refer to the contributing guidelines in the repository for more information on how to submit pull requests, report issues, or request features.
📄 License
This package is released under the MIT License. See the LICENSE file in the package repository for more details.