UNPKG

@uplink-protocol/form-controller

Version:

Reactive multi-step form controller with dynamic validation and state management

176 lines (140 loc) 6.59 kB
# Enhanced Validation System This document explains how to use the enhanced validation system that supports collecting multiple validation errors for a single field and specifying per-validation error messages. ## Overview The form-controller now supports several advanced validation features: 1. **Multiple Error Collection**: Collect and display multiple validation errors for a field rather than stopping at the first error. 2. **Per-Validation Error Messages**: Define specific error messages for each type of validation rule. 3. **Multiple Dynamic Validators**: Apply multiple dynamic validators to a single field, each with its own parameters and error message. These features are particularly useful for complex forms where detailed validation feedback improves user experience. ## How to Use ### Enabling Multiple Error Collection To enable multiple error collection for a field, set the `collectAllErrors` flag in the field's validation object: ```javascript { id: 'password', type: 'password', label: 'Password', validation: { required: true, minLength: 8, pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/, custom: (value) => { if (value.includes('password')) { return 'Password should not contain the word "password"'; } return true; }, errorMessage: 'Please enter a valid password', collectAllErrors: true // Enable multiple error collection } } ``` ### Per-Validation Error Messages You can specify different error messages for each type of validation by using the `errorMessages` object: ```javascript { id: 'password', type: 'password', label: 'Password', validation: { required: true, minLength: 8, pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/, errorMessages: { required: 'Password is required', minLength: 'Password must be at least 8 characters long', pattern: 'Password must include uppercase, lowercase, and numbers' }, collectAllErrors: true } } ``` ### Validation Priority The validation system enforces the following priorities: 1. **Required Validation**: Always checked first. If a field is required and empty, other validations are skipped, following the best practices for form validation. 2. **Type-Specific Validations**: These include email format, min/max length, pattern validation, min/max value validation. 3. **Custom Validation**: User-provided validation functions. 4. **Dynamic Validation**: Context-aware validators registered with the system. ### Getting All Errors When using the `validateField` function with `collectAllErrors` enabled, the result will include an `errors` array with all validation errors: ```javascript const result = validateField(field, value, context, true); if (!result.isValid) { console.log('All errors:', result.errors); // For display purposes, you might want to format these const formattedErrors = result.errors.join(' | '); } ``` ### In the Field Service The FieldService has been updated to support displaying multiple errors. When `collectAllErrors` is enabled for a field, all errors will be combined (with a separator) into a single error message string. ## Multiple Dynamic Validators You can now define multiple dynamic validators for a single field using the `dynamicValidators` array: ```javascript { id: 'username', type: 'text', label: 'Username', validation: { required: true, minLength: 3, maxLength: 20, dynamicValidators: [ { name: 'uniqueUsername', params: { checkExisting: true }, errorMessage: 'This username is already taken' }, { name: 'noSpecialChars', errorMessage: 'Username cannot contain special characters' } ], collectAllErrors: true } } ``` ### Mixing Legacy and New Validators The system maintains backward compatibility with the legacy single dynamic validator syntax: ```javascript { id: 'confirmEmail', type: 'email', label: 'Confirm Email', validation: { // Legacy single validator dynamicValidator: 'equals', dynamicValidatorParams: { targetField: 'email', errorMessage: 'Email addresses must match' }, // New multiple validators dynamicValidators: [ { name: 'emailDomainCheck', params: { allowedDomains: ['company.com', 'partner.org'] }, errorMessage: 'Only company domains are allowed' } ] } } ``` Note: When both approaches are used, all validators will be executed according to the validation priority rules. ## Validation Priority The validation system enforces the following priorities: 1. **Required Validation**: Always checked first. If a field is required and empty, other validations are skipped, following the best practices for form validation. 2. **Type-Specific Validations**: These include email format, min/max length, pattern validation, min/max value validation. 3. **Custom Validation**: User-provided validation functions. 4. **Dynamic Validation**: Context-aware validators registered with the system. ## Benefits * **Better User Experience**: Users can see all validation issues at once, rather than fixing one issue only to encounter another. * **More Specific Error Messages**: Tailored messages for each type of validation make it clearer what's wrong. * **Richer Validation Logic**: Multiple dynamic validators allow for complex validation scenarios without custom code. * **Reduced Form Submissions**: By showing all errors upfront, users can fix everything at once, reducing the number of form submission attempts. * **Flexible Implementation**: You can enable these features on a per-field basis, allowing for targeted use where appropriate. ## Best Practices * Use multiple error collection for complex fields with many validation rules. * Define specific error messages for each validation type to be clear about what's wrong. * Consider using separate error display components that can show errors as a list when multiple errors are present. * Keep your validation error messages concise and clear, especially when multiple might display at once. * Use the new `dynamicValidators` array for all new development (the legacy `dynamicValidator` is deprecated). * Reserve multiple error collection for forms where showing all errors at once would be helpful - for simpler forms, the traditional approach might be more user-friendly.