{"id":22680270,"url":"https://github.com/dugalcedo/formellt","last_synced_at":"2026-02-07T21:32:51.141Z","repository":{"id":263791022,"uuid":"891193988","full_name":"dugalcedo/formellt","owner":"dugalcedo","description":"Lighweight form handler library for vanilla JavaScript or TypeScript.","archived":false,"fork":false,"pushed_at":"2024-11-20T10:26:40.000Z","size":11,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-26T13:57:45.708Z","etag":null,"topics":["form","form-validation","forms","html-form","html-forms","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/formellt","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dugalcedo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-19T22:28:55.000Z","updated_at":"2024-11-20T10:26:44.000Z","dependencies_parsed_at":"2025-11-12T11:01:02.064Z","dependency_job_id":null,"html_url":"https://github.com/dugalcedo/formellt","commit_stats":null,"previous_names":["dugalcedo/formellt"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dugalcedo/formellt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dugalcedo%2Fformellt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dugalcedo%2Fformellt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dugalcedo%2Fformellt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dugalcedo%2Fformellt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dugalcedo","download_url":"https://codeload.github.com/dugalcedo/formellt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dugalcedo%2Fformellt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29208715,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T20:33:12.493Z","status":"ssl_error","status_checked_at":"2026-02-07T20:30:47.381Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["form","form-validation","forms","html-form","html-forms","typescript"],"created_at":"2024-12-09T19:12:57.220Z","updated_at":"2026-02-07T21:32:51.123Z","avatar_url":"https://github.com/dugalcedo.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Formellt\n\nA class for handling forms. Easily sanitize, validate, and display errors.\n\n## Installation\n\n`npm i formellt`\n\n## Usage\n\n### HTML\n\n```html\n\u003c!-- A minimalist example. Please use labels and keep your form accessible. --\u003e\n\n\u003cform\u003e\n    \u003cinput type=\"text\" placeholder=\"username\" name=\"username\"\u003e\n    \u003cspan data-error=\"username\"\u003e\n    \u003cbr\u003e\n\n    \u003cinput type=\"text\" placeholder=\"password\" name=\"password\"\u003e\n    \u003cspan data-error=\"password\"\u003e\n    \u003cbr\u003e\n\n    \u003cinput type=\"text\" placeholder=\"password2\" name=\"password2\"\u003e\n    \u003cspan data-error=\"password\"\u003e\n    \u003cbr\u003e\n\n    \u003cinput type=\"checkbox\" placeholder=\"privacy\" name=\"privacy\"\u003e\n    \u003cspan data-error=\"privacy\"\u003e\n    \u003cbr\u003e\n\n    \u003cbutton\u003e\n        Submit\n    \u003c/button\u003e\n    \u003cspan data-spam-error data-response-error\u003e\n\u003c/form\u003e\n```\n\n### JavaScript\n\n```js\nimport Formellt from \"./index.js\"\n\n//                            ↓ CSS selector or HTMLFormElement\nconst handler = new Formellt(\"#signup-form\", {  // only validator and onSubmit are required in this init object\n    sanitizer(formData) {\n        formData.username = formData.username.trim().replaceAll(/\\s+/gm, \" \")\n        return formData\n    },\n\n    //        ↓ formData if no sanitizer is provided \n    validator(sanitized, dispatchError) {\n        if (!formData.username) {\n            dispatchError(\"username\", \"required\")   // first arg corresponds to the data-error in the spans above\n        } else if (formData.username.length \u003c 4) {\n            dispatchError(\"username\", \"Must be at least 4 characters.\")\n        }\n\n        if (!formData.password) {\n            dispatchError(\"password\", \"required\")\n        } else if (formData.password.length \u003c 8) {\n            dispatchError(\"password\", \"Must be at least 8 characters.\")\n        } else if (formData.password !== formData.password2) {\n            dispatchError(\"password\", \"Passwords musts match.\")\n        }\n\n        if (!formData.privacy.checked) {\n            dispatchError(\"privacy\", \"You must read the privacy policy.\")\n        }\n    },\n\n    //// Handling the submission and responses ///\n    //                      ↓ same as formData if no sanitizer provided\n    onSubmit(_e, formData, sanitized) {\n        // return a response object to trigger the onGoodRes/onBadRes hooks\n        return fetch(\"url-goes-here\", {\n            method: \"POST\",\n            body: JSON.stringify(sanitized)\n        })\n    },\n    onGoodRes(_res, data) {\n        console.log(data)\n    },\n    onBadRes(res, _data) {\n        return `Error ${res.status}: ${res.statusText}`\n        // returned value will render in the element with data-response-error\n    },\n\n    /// Other nifty stuff ///\n    /*\n        PROPERTY                    DATA TYPE               DEFAULT\n\n        validateOnChange:           boolean                 false\n            call the sanitizer and validator any time an input changes\n\n        validateOnMutate:           boolean                 false\n            call the sanitizer and validator if the form's DOM subtree changes\n\n        validateOnMount:            boolean                 false\n            call the sanitizer and validator immediately as the form loads\n\n        allowInvalid:               boolean                 false\n            allow onSubmit to be called even if the form has errors\n\n        preventSpam:                boolean                 false\n            prevent submissions if onSubmit is busy\n\n        spamErrorMsg:               string                  \"Please wait.\"\n            message to display in the element with \"data-spam-error\" if the form is spammed\n\n        submitMsg:                  string                  \"Fix errors.\"\n            message to display in the element with \"data-response-error\"\n            if the form does not pass the validator and allowInvalid is false\n\n        mutationCallback:           MutationCallback        undefined\n            if provided, a mutation observer will be defined that listens for\n            changes in the childList and subtree\n    */\n})\n```\n\n### TypeScript\n\n```ts\nimport Formellt from \"./index.js\"\n\ntype FormData = {\n    username: string\n    password: string\n    password2: string\n    privacy: boolean\n}\n\n// Optional, defaults to FormData\ntype Sanitized = {\n    username: string\n    password: string\n    password2: string\n    privacy: boolean\n}\n\n// Optional, defaults to any\ntype Data = {\n    token: string\n    errorMessage: string\n}\n\nconst handler = new Formellt\u003cFormData, Sanitized, Data\u003e(\"#signup-form\", {\n    /*\n            See JavaScript example above for what the init object should look like\n\n            formData in validator, sanitizer, and onSubmit will be the first type\n            sanitized in onSubmit will be the second type\n            data in onGoodRes and onBadRes will be the third type\n    */\n})\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdugalcedo%2Fformellt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdugalcedo%2Fformellt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdugalcedo%2Fformellt/lists"}