UNPKG

alpinejs-form-validation

Version:

Lightweight, CSS-driven form validation plugin for Alpine.js with real-time validation and data attributes

102 lines (83 loc) 2.95 kB
export function checkInput( el, modifiers, expression, evaluateLater, ignoreDirty = false ) { const hasModifier = (modKey) => modifiers.includes(modKey) const getModifierValue = (modKey) => { const modIndex = modifiers.indexOf(modKey) if (modIndex === -1 || modIndex + 1 >= modifiers.length) { return null } const modValue = Number(modifiers[modIndex + 1]) return isNaN(modValue) ? null : modValue } const getValidationOptionWithValue = (modKey, optionKey) => { if (!hasModifier(modKey)) { return null } const modValue = getModifierValue(modKey) return modValue !== null ? { [optionKey]: modValue } : null } const getErrors = evaluateLater(expression) // Build validation options object - only include options with valid values const validationOptions = { ...(hasModifier('required') && { required: true }), ...getValidationOptionWithValue('min', 'min'), ...getValidationOptionWithValue('max', 'max'), ...getValidationOptionWithValue('min:length', 'minLength'), ...getValidationOptionWithValue('max:length', 'maxLength'), ...(hasModifier('checked') && { checked: true }), } getErrors((inputValue) => { // Skip validation if no input value and element hasn't been interacted with if ( !ignoreDirty && !inputValue && !el.getAttribute('data-validation-dirty') ) { return } // Validation logic mapping const validationChecks = { required: () => !!inputValue, min: () => { const numericValue = Number(inputValue) return !isNaN(numericValue) && numericValue >= validationOptions.min }, max: () => { const numericValue = Number(inputValue) return !isNaN(numericValue) && numericValue <= validationOptions.max }, minLength: () => inputValue.length >= validationOptions.minLength, maxLength: () => inputValue.length <= validationOptions.maxLength, checked: () => !!inputValue, } // Run only applicable validations const validationStatus = {} for (const [optionKey] of Object.entries(validationOptions)) { if (validationChecks[optionKey]) { validationStatus[optionKey] = validationChecks[optionKey]() } } const isValid = Object.values(validationStatus).every(Boolean) const errorKey = Object.keys(validationStatus).find( (statusKey) => !validationStatus[statusKey] ) // Set data attributes const inputAttributes = { 'data-validation-dirty': true, 'data-validation-valid': isValid, 'data-validation-reason': errorKey || '', 'data-validation-status': JSON.stringify(validationStatus), 'data-validation-options': JSON.stringify(validationOptions), } Object.entries(inputAttributes).forEach( ([attributeName, attributeValue]) => { el.setAttribute(attributeName, attributeValue) } ) }) }