
* Added ValidationHooks and attribute to FormControl * Event listener uses data attribute to set type * Changed default event listener to blur * Add validation data attribute to other components * Adjusted querySelector to remove condition * Added nullish operator to prevent error * Added optional chaining to validator
68 lines
2.4 KiB
Text
68 lines
2.4 KiB
Text
---
|
|
import type { HookType } from '@astro-reactive/common';
|
|
|
|
export interface Props {
|
|
hook?: HookType;
|
|
displayErrorMessages?: boolean;
|
|
}
|
|
|
|
const { hook = 'all', displayErrorMessages = false } = Astro.props;
|
|
---
|
|
|
|
<input hidden name="hook" id="hook" value={hook} />
|
|
<input
|
|
hidden
|
|
name="displayErrorMessages"
|
|
id="displayErrorMessages"
|
|
value={displayErrorMessages.toString()}
|
|
/>
|
|
|
|
<script>
|
|
// TODO: selectors should by unique IDs generated by our library
|
|
// TODO: implement type guards pls 😱
|
|
// TODO: create deserializer util
|
|
// TODO: handle hooks / when to attach event listeners
|
|
// const form = document.querySelector('form');
|
|
|
|
import type { ValidatorRules } from '@astro-reactive/common';
|
|
import { clearErrors, validate } from './core';
|
|
|
|
// const hook: HookType = (document.getElementById('hook') as HTMLInputElement).value as HookType;
|
|
const inputs = [...document.querySelectorAll('body *[data-validation-on]')] as HTMLInputElement[];
|
|
|
|
inputs?.forEach((input) => {
|
|
input.addEventListener(input.dataset?.validationOn ?? 'blur', (e: Event) => {
|
|
// NOTE: event target attribute names are converted to lowercase
|
|
const element = e.target as HTMLInputElement;
|
|
const attributeNames = element?.getAttributeNames() || [];
|
|
const validators = attributeNames
|
|
.filter((attribute) => attribute.includes('data-validator-'))
|
|
.map((attribute) => {
|
|
const limit = element.getAttribute(attribute);
|
|
return {
|
|
validator: `${attribute}:${limit}`,
|
|
category: element.getAttribute(`${attribute}-category`),
|
|
};
|
|
})
|
|
.filter((val) => val.category !== null); // Filter out validators without a category
|
|
|
|
const value =
|
|
element.type === 'checkbox' ? (element.checked ? 'checked' : '') : element.value;
|
|
const errors = validate(value, validators as ValidatorRules);
|
|
|
|
// set element hasErrors
|
|
if (errors.length) {
|
|
element.parentElement?.setAttribute(`data-validator-${errors[0]?.category}`, 'true');
|
|
element.setAttribute(`data-validator-${errors[0]?.category}`, 'true');
|
|
element.classList.add(`has-errors`);
|
|
// TODO: display error messages
|
|
} else {
|
|
element.parentElement?.removeAttribute(`data-validator-${errors[0]?.category}`);
|
|
element.removeAttribute(`data-validator-${errors[0]?.category}`);
|
|
element.classList.remove(`has-${errors[0]?.category}`);
|
|
}
|
|
});
|
|
|
|
input.addEventListener('input', clearErrors);
|
|
});
|
|
</script>
|