UNPKG

@spartan-components/sc-form

Version:

A thin wrapper for html form elements to improve error handling.

2 lines (1 loc) 2.23 kB
class e extends HTMLElement{constructor(){super(),this.form=this.querySelector("form"),this.inputs=this.form.querySelectorAll("input, textarea, select"),this.form.setAttribute("novalidate","true"),this.setupEventHandlers()}setupEventHandlers(){this.inputs.forEach((e=>e.addEventListener("blur",this))),this.form.addEventListener("submit",this)}disconnectedCallback(){this.inputs.forEach((e=>e.removeEventListener("blur",this))),this.form.removeEventListener("submit",this)}handleEvent(e){"blur"!==e.type||this.skippableCheckbox(e)||this.checkInput(e.target),"submit"===e.type&&this.checkForm(e)}skippableCheckbox(e){const t="checkbox"===e.target.type,r="checkbox"===e?.relatedTarget?.type,s=e?.relatedTarget?.name===e.target.name;return t&&r&&s}checkInput(e){const t=this.validatableGroupCheckbox(e)?this.validateCheckbox(e):e.validity.valid;t&&this.removeErrorMessage(e),t||this.addErrorMessage(e)}validatableGroupCheckbox(e){const t=e.closest("fieldset"),r=t?.hasAttribute("data-required");if(!r)return!1;return this.querySelectorAll(`input[name=${e.name}]`).length>1}validateCheckbox(e){const t=e.closest("fieldset"),r=new FormData(this.form).getAll(e.name).length>0;return r?e.setCustomValidity(""):e.setCustomValidity(t.dataset.error??"Choose at least one option"),r}isMultiElement(e){return e.name&&this.querySelectorAll(`[name=${e.name}]`).length>1}getErrorData(e){const t=this.isMultiElement(e),r=t?e.closest("fieldset").querySelector("legend"):this.querySelector(`label[for=${e.id}]`),s=t?e.closest("fieldset"):e,i=`${t?e.name:e.id}-error`;return{appendToElement:r,errorElement:s,errorId:i,errorSpan:`<span id=${i}>${e.validationMessage}</span>`}}addErrorMessage(e){this.removeErrorMessage(e);const{appendToElement:t,errorElement:r,errorId:s,errorSpan:i}=this.getErrorData(e);r.setAttribute("aria-invalid","true"),r.setAttribute("aria-describedby",s),t.insertAdjacentHTML("afterend",i)}removeErrorMessage(e){const{errorElement:t,errorId:r}=this.getErrorData(e);t.removeAttribute("aria-invalid"),t.removeAttribute("aria-describedby"),this.form.querySelector(`#${r}`)?.remove()}checkForm(e){this.form.checkValidity()||(e.preventDefault(),this.inputs.forEach((e=>this.checkInput(e))))}}customElements.define("sc-form",e);