{"id":20495341,"url":"https://github.com/kevinast/svelte-native-forms","last_synced_at":"2026-05-29T12:31:57.550Z","repository":{"id":52583808,"uuid":"339177593","full_name":"KevinAst/svelte-native-forms","owner":"KevinAst","description":"minimalist form validation with powerful results","archived":false,"fork":false,"pushed_at":"2021-04-24T20:52:25.000Z","size":1562,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-05T18:28:54.263Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/KevinAst.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-15T19:00:29.000Z","updated_at":"2021-04-24T20:36:17.000Z","dependencies_parsed_at":"2022-09-23T18:50:50.390Z","dependency_job_id":null,"html_url":"https://github.com/KevinAst/svelte-native-forms","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/KevinAst/svelte-native-forms","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KevinAst%2Fsvelte-native-forms","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KevinAst%2Fsvelte-native-forms/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KevinAst%2Fsvelte-native-forms/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KevinAst%2Fsvelte-native-forms/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/KevinAst","download_url":"https://codeload.github.com/KevinAst/svelte-native-forms/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KevinAst%2Fsvelte-native-forms/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33652979,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2024-11-15T17:45:35.014Z","updated_at":"2026-05-29T12:31:57.530Z","avatar_url":"https://github.com/KevinAst.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# svelte-native-forms\n\n*... minimalist form validation with powerful results*\n\n\u003c!---  FOLLOWING PARAGRAPH \n       REFINED FROM: Constraint Validation: Native Client Side Validation for Web Forms\n                     ... https://www.html5rocks.com/en/tutorials/forms/constraintvalidation/\n       Validating forms has notoriously been a painful development\n       experience. Implementing client side validation in a user friendly,\n       developer friendly, and accessible way is hard. Before HTML5 there was\n       no means of implementing validation natively; therefore, developers\n       have resorted to a variety of JavaScript based solutions.\n ---\u003e \n\nValidating forms has notoriously been a painful development\nexperience.  Implementing client side validation _in a user friendly\nway **is a tedious and arduous process**_\n\u0026bull; you want to validate fields only at the appropriate time _(when the\nuser has had the chance to enter the data)_\n\u0026bull; you want to present validation errors in a pleasing way\n\u0026bull; you may need to apply custom validation _(specific to your\napplication domain)_\n\u0026bull; etc.\n\n\u003c!--- AI: should following sentence reference HTML5's Constraint Validation https://developer.mozilla.org/en-US/docs/Web/API/Constraint_validation ---\u003e \n\nEven with the introduction of [HTML5's Form Validation], it is still\noverly complex, and doesn't address many common scenarios _(mentioned\nabove)_.  Without the proper approach, form validation can be one of\nthe most difficult tasks in web development.\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n**Overview:**\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\n**svelte-native-forms** _(\u003cmark\u003eaka **SNF**\u003c/mark\u003e)_ is a [svelte] utility that\nfacilitates field validation in your native html forms.\n\nThe term _**native**_ refers to the utilization of the native HTML\n`\u003cform\u003e` tag and the corresponding form elements (`\u003cinput\u003e`,\n`\u003cselect\u003e`, `\u003ctextarea\u003e`, etc.).  In other words, **SNF** does NOT\nintroduce components for these abstractions, rather you use the native\nhtml representations.\n\nHere are some **key points** to understand:\n\n- **SNF** is based on **svelte actions**.  By applying a simple action\n  to your form elements, the basics of the form validation control is\n  defined right in your html markup _... see [Native HTML Forms]_.\n  \n- **SNF** improves user experience by validating fields at the\n  appropriate time _... see [Validation Timing]_.\n  \n- **SNF** provides two simple reactive error display components, that\n  \"auto wires\" themselves to the appropriate form/fields, dynamically\n  displaying form-based errors as needed _... see [Reactive Error\n  Display]_.\n\n- **SNF** supports the native [HTML5 Form Validation], by using\n  the standard validation attributes in your form elements, such as\n  `type`, `required`, `minlength`, etc. _... see [Built-In Form\n  Validation]_.\n\n- **SNF** allows you to easily apply **custom validations**, where your\n  JavaScript code can perform app-specific validation _(even\n  involving cross field validations)_\n  _... see [Custom Validation]_.\n  \n- **SNF** is customizable\n  **\u0026bull; don't like the error display format?** _... that is easily resolved_\n  **\u0026bull; want to perform a custom field validation?** _... easy peasy_\n  _... see [Customization]_.\n\n\n**SNF** promotes a \u003cmark\u003e**clean and simple approach**\u003c/mark\u003e to form\nvalidation, that yields \u003cmark\u003e**powerful results**\u003c/mark\u003e.\n\n\u003cmark\u003e**Important NOTE**\u003c/mark\u003e: **SNF** is intended to be used by applications\nthat employ native html forms and form elements.  Because of\n**SNF**'s usage of svelte actions, **this is a hard restriction**!\n_Svelte actions may only be applied to native DOM elements - **not**\ncomponents_.  **If you are a minimalist** _(using native html)_, you will\nappreciate this abstraction of form/field validation.  **If you are\nusing a more inclusive UI library**, it most likely already promotes\nForm/Element component abstractions _(which will typically provide a\ntechnique to handle form validation)_.\n\n\u003c/ul\u003e\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## At a Glance\n\n- [Install]\n- [Basic Example]\n- [Concepts]\n  - [Native HTML Forms]\n  - [Validation Timing]\n  - [Reactive Error Display]\n  - [Built-In Form Validation]\n  - [Custom Validation]\n- [Actions]\n  - [`formChecker`]\n  - [`fieldChecker`]\n- [Components]\n  - [`\u003cFormErr\u003e`]\n  - [`\u003cFieldErr\u003e`]\n- [Controllers]\n  - [`formController`]\n- [Advanced Concepts]\n  - [Svelte Bound Variables]\n- [Customization]\n  - [Error Look and Feel]\n- [Competition]\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Install\n\n?? Installation\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Basic Example\n\nHere is a very basic example of **SNF** usage:\n\n?? AI: would be nice to highlight the SNF specifics (NOT POSSIBLE IN quoted stuff) ?? consider an image?\n\n```html\n\u003cscript\u003e\n import {formChecker,  FormErr,\n         fieldChecker, FieldErr} from 'svelte-native-forms';\n\n const submit     = (event, fieldValues) =\u003e alert(`Successful submit (all fields are valid)!`);\n const isIdUnique = ({id}) =\u003e id==='dup' ? 'ID must be unique' : '';\n\u003c/script\u003e\n\n\u003cform use:formChecker={{submit}}\u003e\n  \u003clabel\u003e\n    Name:\n    \u003cinput id=\"name\" name=\"name\" type=\"text\" required minlength=\"3\"\n           use:fieldChecker\u003e\n    \u003cFieldErr/\u003e\n  \u003c/label\u003e\n\n  \u003clabel\u003e\n    ID:\n    \u003cinput id=\"id\" name=\"id\" type=\"text\" required minlength=\"2\" maxlength=\"10\"\n           use:fieldChecker={{validate: isIdUnique}}\u003e\n    \u003cFieldErr/\u003e\n  \u003c/label\u003e\n\n  \u003ccenter\u003e\n    \u003cFormErr/\u003e\n  \u003c/center\u003e\n  \u003ccenter\u003e\n    \u003cinput type=\"submit\" value=\"Make It SO!\"\u003e\n  \u003c/center\u003e\n\u003c/form\u003e\n```\n\nAt it's core, this example is using HTML's standard [Built-In Form\nValidation].  However with the simple injection **SNF**'s `Checker`\nactions, and **SNF**'s **error display** components, a sophisticated\ncontrol structure has been applied that promotes a very usable form.\nWe have even seamlessly introduced a **custom field validation**!\n\n?? IMG: show result\n\nYou can interact with this example in the following ?REPL.\n\nHere are some points of interest:\n\n- the `use:formChecker` action is applied to the `\u003cform\u003e`\n\n  - a `submit` function is registered to this action.  This is used in\n    lue of the standard `on:submit` event.  This function is invoked\n    on a standard `submit` request, but **only when all fields pass\n    validation**.  If there are field errors, the appropriate messages\n    are displayed, and no submit occurs.\n\n- the `\u003cinput\u003e` form elements are employing some standard [Built-In\n  Form Validation] constraints _(`type`, `required`, `minlength`, etc.)_.\n\n- the `use:fieldChecker` actions are applied to each `\u003cinput\u003e` form\n  element.  This completes the knowledge transfer of your form\n  structure to **SNF**. (AI: can this be implied when all defaults are\n  used?)\n\n  - a **custom field validation** has been introduced _(for the `id`\n    field)_, by using the `validate` action parameter.  This invokes a\n    function that can apply application-specific validations.  The\n    function merely returns an error string _(if invalid)_, or an empty\n    string _(when valid)_.\n\n  - the `\u003cFieldErr/\u003e` components will dynamically bind to the input field\n    of interest, and conditionally display appropriate errors for that\n    field.\n\n- the `\u003cFormErr/\u003e` component dynamically binds to the form, and and\n  conditionally displays an appropriate error when a submit is\n  requested on an invalid form.\n\n- a standard `submit` control is applied to the form.  As mentioned\n  above, the **SNF** `submit` function is only invoked when all fields\n  pass validation.\n\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Concepts\n\n**svelte-native-forms** _(\u003cmark\u003eaka **SNF**\u003c/mark\u003e)_ is a [svelte]\nutility that facilitates field validation in your native html forms.\n\nThe following sections discuss the basic concepts of **SNF**:\n\n- [Native HTML Forms]\n- [Validation Timing]\n- [Reactive Error Display]\n- [Built-In Form Validation]\n- [Custom Validation]\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Native HTML Forms\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\nIn **SNF**, your interactive forms continue to use the native HTML\n`\u003cform\u003e` tag along with the corresponding form elements (`\u003cinput\u003e`,\n`\u003cselect\u003e`, `\u003ctextarea\u003e`, etc.).  In other words, **SNF** does NOT\nintroduce components for these abstractions, rather you use the native\nhtml representations.\n\nThis is accomplished by using **svelte actions**. By applying a simple\naction to your form elements, the basics of the form validation\ncontrol is defined right in your html markup.\n\nThis represents a different approach from other form validation\nlibraries.  Some may require you to define a separate JavaScript\ncontrol structure that either drives your html markup, or duplicates\nthe html hierarchy in some way.  Others may introduce their own\ncomponent layer on top of the native form elements.\n\nBecause **SNF** is action-based, it can utilize your DOM hierarchy\nto implicitly define the validation control structure, _making it a\nsimple and understandable **single source of truth**_.  In other words, _**your form\nvalidation control is defined right in your html markup!**_\n\n\u003c/ul\u003e\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Validation Timing\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\nValidation timing is an important characteristic in achieving a better\nuser experience.  You don't want to overwhelm your users by validating\nevery field from the start, yet once a field has been seen, validation\nis more appropriate.\n\n**SNF** employs a validation heuristic, where fields are validated\nat the appropriate time:\n\n- only when they have been seen by the user _(i.e. touched)_, \n- or when a submit has been attempted. \n\nThe \"touched\" determination is made through focus semantics.  A field is\nconsidered to have been touched when it has gone in and out of focus\n(i.e. blur).\n\nThis heuristic is a common technique that is tedious to accomplish,\n_when attempted in application code_.\n\n\u003c/ul\u003e\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Reactive Error Display\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\n**SNF** provides two reactive error display components that\ndynamically display appropriate errors as needed.  The beauty of these\ncomponents are that they auto-wire themselves to the appropriate\nerror.  As a result, they are very simple to use.\n\nIn the following example, the mere inclusion of `\u003cFieldErr/\u003e` will\ndynamically display any **name-field** errors at the appropriate time,\nsimply because it is contained in the `\u003clabel\u003e` that holds the\n**name** `\u003cinput\u003e` _(this is not the only way to bind errors, but a\nvery common one)_:\n\n```html\n\u003clabel\u003e\n  Name:\n  \u003cinput id=\"name\" name=\"name\" type=\"text\" required minlength=\"3\"\n         use:fieldChecker\u003e\n  \u003cFieldErr/\u003e\n\u003c/label\u003e\n```\n\nThere are two reactive error display components:\n\n- [`\u003cFormErr\u003e`]: for displaying form errors\n- [`\u003cFieldErr\u003e`]: for displaying field errors\n\n\n\u003c/ul\u003e\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Built-In Form Validation\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\nWeb standards provide a native way to achieve client-side validation\n_(see [HTML5 Form Validation])_.  This is accomplished by simply\napplying validation attributes to your form elements, such as `type`,\n`required`, `minlength`, `maxlength`, `min`, `max`, `pattern`, etc.\n\nRoughly speaking, this standard is broken up into two parts:\n\n- **validation** _(i.e. built-in validation)_:\n\n  **SNF** supports the continued use of built-in validation, _in\n  addition to the ability to easily inject [Custom Validation]_.  In\n  other words, you may continue to use the HTML validation attributes\n  _(mentioned above)_.  All built-in validation messages are presented\n  to the user before any custom validations.\n\n- **presentation** _(of validation errors)_:\n\n  The error presentation provided by standard HTML is somewhat\n  primitive and unrefined.  It is for this reason that **SNF** takes\n  over the the presentation of validation errors.  This _(in\n  conjunction with **SNF**'s **powerful validation heuristic**)_,\n  provides a **much improved user experience**.\n\n**SNF** accomplishes this by applying the `novalidate` attribute to\nyour `\u003cform\u003e` element.  While this disables the **presentation**\naspects of the standard, it leaves the constraint validation API\nintact _(along with CSS pseudo-classes like `:valid` etc.)_.  This\nallows **SNF** to continue to interpret and support the built-in form\nvalidations!\n\n\u003c/ul\u003e\n\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Custom Validation\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\nYou can easily apply **custom validations**, where your JavaScript\ncode provides app-specific validation.  This even includes more\ncomplex things, such as cross field validation!\n\nThis is accomplished through the `validate` parameter of the\n[`fieldChecker`] action.\n\nThe following simple example confirms that the `id` field is unique,\n_based on an app-specific `isUnique()` function_.\n\n```html\n\u003cinput id=\"id\" name=\"id\" type=\"text\" required\n       use:fieldChecker={{validate: ({id}) =\u003e isUnique(id) ? '' : 'ID must be unique''}}\u003e\n```\n\nThe `validate` hook can employ any logic _(as complex or simple as\nneeded)_, and can reason about multiple fields _(not just one)_.\nUltimately it returns a string - which is either an **error** _(for\nnon-empty strings)_ or **valid** _(for an empty string)_.\n\n\u003c/ul\u003e\n\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Actions\n\nThe primary instrument that **SNF** uses are **svelte actions**!  There are two:\n\n1. [`formChecker`]: to be applied to your `\u003cform\u003e` element\n2. [`fieldChecker`]: to be applied to your interactive form elements (`\u003cinput\u003e`, `\u003cselect\u003e`, `\u003ctextarea\u003e`, etc.)\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## `formChecker`\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\nThe `formChecker` svelte action is applied to your html `\u003cform\u003e`\nelement.  It registers the form to **SNF** control, allowing it\norchestrate form validation.\n\n**Action Usage:**\n\n```html\n\u003cscript\u003e\n import {formChecker} from 'svelte-native-forms';\n\n const submit = (event, fieldValues) =\u003e alert(`Successful submit (all fields are valid)!`);\n\u003c/script\u003e\n\n\u003cform use:formChecker={{submit}}\u003e\n  ... snip snip\n\u003c/form\u003e\n```\n\n**Action Parameters:**\n\nThe `formChecker` action supports the following parameters:\n\n- **`submit`**: a required submit function that executes a\n  client-specific process.  This is invoked when a submit occurs, only\n  when all fields pass validation.\n\n  **submit() API:**\n  ```\n  + submit(event, fieldValues): void\n    NOTE: All field values (monitored by SNF) are passed as named parameters.\n  ```\n\n- **`errStyles`**: an optional object containing the in-line styles to\n  apply to input elements that are in error.\n\n  - use an object with in-line styling pairs: camelCaseKey/value\n  - or `null` to disable\n   \n  **DEFAULT**:\n  ```\n  {\n    border:          '2px solid #900', ... solid red border\n    backgroundColor: '#FDD',           ... pink background\n  }\n  ```\n\n**formController:**\n\nThe `formChecker` action promotes a `formController` API through\nwhich your application can programmatically make various form-specific\nrequests _(like resetting the form)_.  Please refer to the\n[`formController`] section for a discussion of this API _(and how to\naccess it)_.\n\n\u003c/ul\u003e\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## `fieldChecker`\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\nThe `fieldChecker` svelte action is applied to your interactive form\nelements (`\u003cinput\u003e`, `\u003cselect\u003e`, `\u003ctextarea\u003e`, etc.).  It registers\nthe form element to **SNF** control, allowing it to participate in the\nform's validation.  In addition it injects the form value into the set\nof `formFields` passed to your submit function.\n\nIf your field has **no validation** constraints, this action is\ncompletely optional.  The only down-side to omitting the action is\nthat the field value will NOT be included in the set of `formFields`\npassed to your submit function.\n\nForm elements containing this action **must have** a `name` or `id`\nattribute.  While this is a common form requirement, in the case of\n`fieldChecker`, it derives it's `fieldName` from these attributes\n_(the `name` attribute takes precedence over `id`)_.\n\nAI: ?? per web standards I think a form submission REQUIRES a `name` attribute\n- however **SNF** may need id to sync up various elements\n- this may need to be tweaked (however we need to play with ALL the form elements)\n\n\n**Action Usage:**\n\n```html\n\u003cscript\u003e\n import {formChecker} from 'svelte-native-forms';\n\u003c/script\u003e\n\n... in the context of a form:\n\n    ... NO action parameters (all defaulted)\n    \u003cinput id=\"name\" name=\"name\" type=\"text\" required minlength=\"3\"\n           use:fieldChecker\u003e\n\n    ... WITH action parameters\n    \u003cinput id=\"name\" name=\"name\" type=\"text\" required minlength=\"3\"\n           use:fieldChecker={{validate, initialValue: 'WowZee'}}\u003e\n  \n... snip snip\n```\n\n**Action Parameters:**\n\nThe `fieldChecker` action supports the following parameters _(all optional)_:\n\n- **`validate`**: an optional function that applies custom\n  client-specific validation to this field.\n\n  **DEFAULT**: NO custom validation is applied ... only [Built-In Form\n  Validation] _(e.g. `type`, `required`, `minlength`, etc.)_\n\n  **validate() API:**\n  ```\n  + validate(fieldValues): errMsgStr (use '' for valid)\n    NOTE: All field values are passed as named parameters,\n          supporting complex inner-dependent field validation\n            EX: validate({address, zip}) ...\n          Typically you only access the single field being validated\n            EX: validate({address}) ...\n  ```\n\n  **validate() example:** ?? more realistic\n  ```js\n  function validate({foo}) {\n    return foo==='dup' ? 'foo must be unique' : '';\n  }\n  ```\n\n- **`initialValue`**: optionally, the initial value to apply to this\n  field, both on DOM creation and `reset()` functionality.\n\n  **DEFAULT**: NO initial value is programmatically applied.  In other\n  words the initial value is strictly defined by your html.\n\n- **`boundValue`**: optionally, the application variable bound to this\n  fieldNode.  This is required when svelte's `bind:value` is in affect\n  _(due to a web limitation, see: [Svelte Bound Variables])_.\n\n- **`changeBoundValue`**: optionally, a client function that changes\n  it's bound value.  This is required when **SNF**'s `initialValue`\n  and `boundValue` are in affect _(also due to the same web limitation,\n  see: [more when `initialValue` in use ...])_.\n\n  **changeBoundValue() API:**\n  ```\n  + changeBoundValue(initialValue): void\n    ... the implementation should update the client boundValue to the supplied initialValue\n  ```\n\n\u003c/ul\u003e\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Components\n\n**SNF** promotes two reactive components that display form-based error\nmessages in your application:\n\n- [`\u003cFormErr\u003e`]: for displaying form errors\n- [`\u003cFieldErr\u003e`]: for displaying field errors\n\nThe beauty of these components are that they auto-wire themselves to\nthe appropriate error.  As a result, they are very simple to use.\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## `\u003cFormErr\u003e`\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\nThe `\u003cFormErr\u003e` component dynamically displays a generalized message\nwhen something is wrong with one or more form fields.  The default\nmessage is: \u003cspan style=\"font-size: 80%; font-weight: bold;\ncolor:red;\"\u003ePlease correct the highlighted field errors\u003c/span\u003e but can\neasily be overwritten through the `errMsg` property.\n\n`\u003cFormErr\u003e` \u003cmark\u003emust be a descendant of\u003c/mark\u003e a `\u003cform\u003e` that is\ncontrolled by a `formChecker` action.  This is how it implicitly\nauto-wires itself to the form's error status.\n\n**Usage:**\n\n```html\n\u003cform use:formChecker={{submit}}\u003e\n  ... snip snip\n  \u003cFormErr/\u003e\n\u003c/form\u003e\n```\n\n**Visual:**\n\n?? screen shot\n\n**API:**\n```\n\u003cFormErr [errMsg={}]    ... the generalized form-based error message\n                            DEFAULT: \"Please correct the highlighted field errors\"\n         [DispErr={}]/\u003e ... the display component that renders the error\n                            ACCEPTS: errMsg property ... an empty string ('') represents NO error\n                            DEFAULT: the standard internal error display component\n```\n\n**Customization:**\n\nPlease refer to the [Error Look and Feel] section to see how you can\ncustomize the display of your error messages _(using the `DispErr`\nproperty)_.\n\n\u003c/ul\u003e\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## `\u003cFieldErr\u003e`\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\nThe `\u003cFieldErr\u003e` component dynamically displays a field-specific\nmessage when the field it is monitoring is invalid.\n\nThis component auto-wires itself to the monitored field of interest\neither through the `forName` property, or implicitly through\nit's placement within a `\u003clabel\u003e` container _(see **Usage** below)_.\n\n**Usage** _(via `forName`)_:\n\n\u003cul\u003e\n\n```html\n\u003cFieldErr forName=\"zip\"/\u003e\n```\n\nIn this case, the monitored field is identified through the **SNF**\ndefined `fieldName` _(which can be the DOM `name` or `id` attributes,\n`name` taking precedence)_.\n\nExample: `\u003cinput id=\"wow\" name=\"zip\" use:fieldChecker ...\u003e`\n\n\u003c/ul\u003e\n\n\n**Usage** _(via implicit `label` containment)_:\n\n\u003cul\u003e\n\n```html\n\u003clabel\u003e\n  Zip:\n  \u003cinput name=\"zip\" type=\"text\" required use:fieldChecker\u003e\n  \u003cFieldErr/\u003e\n\u003c/label\u003e\n```\n\nIn this case, the monitored field is implicitly identified through\nit's placement in a `\u003clabel\u003e` container.  Both the field and\n`\u003cFieldErr\u003e` are nested in a `\u003clabel\u003e` element.  This is similar to\nhow an `\u003cinput\u003e` element can be implicitly associated to it's\n`\u003clabel\u003e`.\n\n\u003c/ul\u003e\n\n\n**Visual:**\n\n?? screen shot\n\n**API:**\n```\n\u003cFieldErr [forName=\"\"]   ... identifies the field to monitor errors on, as defined by the SNF\n                             fieldName (which can be the DOM name or id attributes, name taking\n                             precedence)\n                             DEFAULT: implicit \u003clabel\u003e containment\n          [DispErr={}]/\u003e ... the display component that renders the error\n                             ACCEPTS: errMsg property ... an empty string ('') represents NO error\n                             DEFAULT: the standard internal error display component\n```\n\n**Customization:**\n\n\nPlease refer to the [Error Look and Feel] section to see how you can\ncustomize the display of your error messages _(using the `DispErr`\nproperty)_.\n\n\u003c/ul\u003e\n\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Controllers\n\n**SNF** promotes public APIs through which application code can\nprogrammatically make various requests.\n\n- These API's are created and promoted by **SNF** actions, and\n  therefore are scoped to the DOM controlled by the action.\n\n- Access to these API's are provided through event handlers. The\n  reason for this is there is **no direct way to return content from\n  svelte actions**.  Please refer to content _(below)_ for details on\n  each controller.\n  \n- _**While this probably goes without saying**_, these APIs should not\n  be used outside the scope of the action that created them.  As an\n  \"internal note\", there is no process by which an event notification\n  can mark them as stale, because the action-attached DOM element has\n  already been removed prior to any action life-cycle notification.\n\n  If the application violates this tenet, the API will throw an Error\n  such as:\n  \n  ```\n  ***ERROR*** formController.reset(): stale reference, the formCheckerAction DOM has been removed!\n  ```\n\n- These APIs promote **true functions (not methods)**.  In other words\n  their execution does **not** require a `controller` dereference.  As\n  an example, the following snippet retains a \"function only\"\n  _(without invocation)_ ... so on event handler invocation, it is\n  truly a function:\n  \n  ```html\n  \u003cbutton on:click|preventDefault={formController.reset}\u003eReset\u003c/button\u003e\n  ```\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## `formController`\n\n\u003cul\u003e\n\nThe `formController` is specific to a `\u003cform\u003e` _(i.e. the\n[`formChecker`] action)_.\n\n\n**`formController` API:**\n\n_Currently, this API promotes only one function (but provides a place\nfor future expansion)_.  \n\n```\n{\n  + reset(): void ... reset the form back to it's original state.\n}\n```\n\nHere are the specifics of each function:\n\n- `+ formController.reset(): void`\n\n  This resets the form back to it's original state, including:\n\n  - initial field values _(as supplied through the [`fieldChecker`]\n    `initialValue` action parameter)_\n  - clear all error state _(both form and fields)_\n    * form error message\n    * field error messages\n  - reset **Validation Timing** heuristics _(both form and fields)_\n    * form as \"submit NOT attempted\"\n    * fields as \"not been touched\"\n\n  A reset is useful when a form is re-used by retaining it's DOM\n  representation _(say when used in a form-based dialog)_.\n\n\n**Accessing `formController`:**\n\nBecause svelte actions have **no direct way to return content to the\nclient**, a `form-controller` event is emitted that contains the\n`formController` _(found in `event.detail.formController`)_.  The\napplication can simply monitor this event _(on the `\u003cform\u003e` element)_,\nand retain the `formController` for it's use.  Here is an example:\n\n```html\n\u003cscript\u003e\n let formController;\n ... snip snip\n\u003c/script\u003e\n\n\u003cform use:formChecker={{submit}}\n      on:form-controller={ (e) =\u003e formController = e.detail.formController }\u003e\n  ... snip snip\n\u003c/form\u003e\n```\n\n\u003c/ul\u003e\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Advanced Concepts\n\nThe following sections discuss more advanced concepts of **SNF**:\n\n- [Svelte Bound Variables]\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Svelte Bound Variables\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\nA very powerful feature of svelte is it's ability to provide a two-way\nbinding between form elements and JS variables.  By simply using the\n`bind:` directive these two aspects are kept \"in sync\".  For example:\n\n```html\n\u003cscript\u003e\n\tlet name = 'World';\n\u003c/script\u003e\n\n\u003cinput id=\"name\" name=\"name\"\n       bind:value={name}\u003e\n\n\u003ch1\u003eHello {name}!\u003c/h1\u003e\n```\n\nFor **SNF** usage, when two-way bindings are in affect, the\n`boundValue` parameter must be specified in the [`fieldChecker`]\naction.  For example:\n\n```html\n\u003cinput id=\"name\" name=\"name\"\n       bind:value={name}\n       use:fieldChecker={{boundValue: name}}\u003e\n```\n\n_**Why is this required?  It seems a bit cumbersome!**_\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\nAs it turns out, this has nothing to do with svelte or the **SNF**\nlibrary.  Rather it is a limitation of the web itself, where updates\nto `fieldNode.value` **do not** emit any web events _(such as the\n`on:input` event)_.\n\n- Svelte manages it's two-way binding by directly managing the\n  `fieldNode.value`.\n  \n- By default, **SNF** monitors form element changes through the \n  `on:input` event.\n\nBecause of this web limitation, **SNF** requires visibility to\n`boundValues`, in order to have access to a \"single source of truth\".\nThis is unfortunate, but there is nothing we can do about it :-(\n\n\u003c/ul\u003e\n\n### more when `initialValue` in use ...\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\nThis limitation gets worse, when you specify an `initialValue` for\nbound elements.  In this scenario **SNF** must update the \"single\nsource of truth\", which _(in this case)_ is the `boundValue`.  This\ncannot be accomplished by **SNF** directly, because the svelte\ncompiler must have visibility of this change.  As a result, when BOTH\n`initialValue` and `boundValue` are in affect, the client must also\nspecify a `changeBoundValue` function.  For example:\n\n```html\n\u003cinput id=\"name\" name=\"name\"\n       bind:value={name}\n       use:fieldChecker={{\n         initialValue: 'WowZee',\n         boundValue: name,\n         changeBoundValue: (initialValue) =\u003e name = initialValue\n       }}\u003e\n```\n\n**changeBoundValue() API:**\n```\n+ changeBoundValue(initialValue): void\n  ... the implementation should update the client boundValue to the supplied initialValue\n```\n\n\u003c/ul\u003e\n\n\u003c/ul\u003e\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Customization\n\n**SNF** is customizable!\n\n- **don't like the error display format?** _... that is easily resolved_\n- **want to perform a custom field validation?** _... easy peasy_\n\nThe following sections discuss various **customization features**:\n\n- [Error Look and Feel]\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Error Look and Feel\n\n\u003cul\u003e\u003c!--- indentation hack for github - other attempts with style is stripped (be careful with number bullets) ---\u003e \n\n**SNF** provides two reactive error display components that\ndynamically display appropriate errors as needed ([`\u003cFormErr\u003e`] and\n[`\u003cFieldErr\u003e`]).  \n\n**The \"Look and Feel\" of these components can easily be overridden.**\nThey merely monitor the appropriate reflective error state, and defer\ntheir display to an internal `\u003cDispErr\u003e` component _(passing the\n`errMsg` to display ... where an empty string (`''`) represents no error)_.\n\nThis display component is extremely simple!  It styles and displays\nthe message using animation.  Here is the default implementation:\n\n**DispErr.svelte** _... the **DEFAULT** internal display component_\n```html\n\u003cscript\u003e\n import {fade} from 'svelte/transition';\n export let errMsg;\n\u003c/script\u003e\n\n{#if errMsg}\n  \u003cspan class=\"error\" transition:fade\u003e\n    {errMsg}\n  \u003c/span\u003e\n{/if}\n\n\u003cstyle\u003e\n .error {\n   font-size:    80%;\n   font-weight:  bold;\n   font-style:   italic;\n   color:        #900;\n }\n\u003c/style\u003e\n```\n\nBecause of it's simplicity, you can easily implement your own display\ncomponent and pass it to [`\u003cFormErr\u003e`]/[`\u003cFieldErr\u003e`] through the\n`DispErr` property.  Simply use the `DispErr.svelte` _(above)_ as a\npattern.  _**You can tailor the style and animation to your\napplication needs!**_\n\nHere is an example that overrides the default:\n\n```html\n\u003cFormErr DispErr={MyErrComp}/\u003e\n```\n\nAI: ?? Provide a full-blown example that overrides the internal DispErr component.  Here are some ideas:\n\n- NOTE: this covers BOTH FieldErr and FormErr\n- change the animation\n- change the error display into a red box via the following form style:\n  ```\n  \u003cstyle\u003e\n   .formError {\n     padding:          0.3em;\n     font-size:        80%;\n     color:            white;\n     background-color: #900;\n     border-radius:    5px;\n     box-sizing:       border-box;\n   }\n  \u003c/style\u003e\n  ```\n- here is the corresponding field style (a red box with square top so it looks like part of the input):\n  ```\n  \u003cstyle\u003e\n   .fieldError {\n     width:            100%;\n     padding:          0.3em;\n     font-size:        80%;\n     color:            white;\n     background-color: #900;\n     border-radius:    0 0 5px 5px;\n     box-sizing:       border-box;\n   }\n  \u003c/style\u003e\n  ```\n\n\u003c/ul\u003e\n\n\n\u003c!--- *** Section ************************************************************************* ---\u003e \n## Competition\n\nQuick review of current validation utils on [\"made with svelte\"] ...\n\n**\u003cmark\u003eBOTTOM LINE\u003c/mark\u003e**\n- think twice about joining the mix\n- there is a lot to think about here\n- may be too time consuming\n- there are a couple of form/validation libs that look robust\n\n\n\n**sveltejs-forms**\n\u003cul\u003e\nDeclarative Forms (KJB: NO NO NO: full form library)\n\n- https://madewithsvelte.com/sveltejs-forms\n- https://github.com/mdauner/sveltejs-forms\n- https://www.npmjs.com/package/sveltejs-forms \u003c\u003c\u003c 400 weekly downloads\n\n\u003c/ul\u003e\n\n\n\n**\u003cmark\u003eSveltik\u003c/mark\u003e**\n\u003cul\u003e\nForm Library inspired by Formik (KJB: MAY BE minimalist COMPETITION \u003c\u003c\u003c looks robust)\n\n- https://madewithsvelte.com/sveltik\n- https://nathancahill.com/sveltik/introducing\n- https://github.com/nathancahill/sveltik\n- https://www.npmjs.com/package/sveltik \u003c\u003c\u003c 323 weekly downloads\n- \u003cmark\u003eNOT sure I like\u003c/mark\u003e the `let:xxx` usage, HOWEVER this may open it up to BOTH native/component forms\n\n```\n* seems lightweight\n* communicates with let:xxx directives\n* can use native form/formElm\n* has a \u003cSveltik\u003e component that can wrap the entire native form (again communicating via let:xxx)\n* also has option of \u003cForm\u003e/\u003cField\u003e components\n  KOOL: they can actually wrap native elms (using slots) \u003c\u003c\u003c this is what I should do in my ErrorMsg\n* have \u003cErrorMessage\u003e component ... must tell it what it's used for (just like mine)\n  \u003cErrorMessage name=\"email\" as=\"div\"/\u003e\n```\n\u003c/ul\u003e\n\n\n\n**\u003cmark\u003eSvelte Forms Lib\u003c/mark\u003e**\n\u003cul\u003e\nLightweight Library for Managing Forms - inspired by Formik (KJB: MAY BE minimalist COMPETITION \u003c\u003c\u003c looks robust)\n\n- https://madewithsvelte.com/svelte-forms-lib\n- https://svelte-forms-lib-sapper-docs.tjin.now.sh/introduction \u003c\u003c\u003c extensive docs\n- https://github.com/tjinauyeung/svelte-forms-lib\n- https://www.npmjs.com/package/svelte-forms-lib \u003c\u003c\u003c 700 weekly downloads\n\n```\n* must setup some structure\n  - uses what it calls observables WHICH I think are Svelte stores\n  - BASED ON THIS, it seems a bit complicated to use\n* but then use native \u003cform\u003e \u003cinput\u003e too\n  - it also has \"Helper components\"\n  - it has styling overrides (via global classes)\n* custom validation is very similar to mine (is procedural), \n  however it has ONE form validator function that must set errors for all fields \u003c\u003c\u003c hmmmm\n```\n\u003c/ul\u003e\n\n\n\n**Svelte Svelte Formly**\n\u003cul\u003e\nA Form Generator (KJB: NO NO NO)\n\n- https://madewithsvelte.com/svelte-formly\n- https://github.com/arabdevelop/svelte-formly\n- https://www.npmjs.com/package/svelte-formly \u003c\u003c\u003c 50 downloads a week\n\n```\n* must setup some structure\n  - seems kinda clunky\n* THEN you have a single \u003cField {fields}\u003e \u003c\u003c\u003c suspect is too intrusive/opinionated\n  - i.e. it is a generator\n```\n\u003c/ul\u003e\n\n\n\n\n\n\n\u003c!--- *** REFERENCE LINKS ************************************************************************* ---\u003e \n\n\u003c!--- **SNF** ---\u003e \n[Install]:                               #install\n[Basic Example]:                         #basic-example\n[Concepts]:                              #concepts\n  [Native HTML Forms]:                   #native-html-forms\n  [Validation Timing]:                   #validation-timing\n  [Reactive Error Display]:              #reactive-error-display\n  [Built-In Form Validation]:            #built-in-form-validation\n  [Custom Validation]:                   #custom-validation\n[Actions]:                               #actions\n  [`formChecker`]:                       #formchecker\n  [`fieldChecker`]:                      #fieldchecker\n[Components]:                            #components\n  [`\u003cFormErr\u003e`]:                         #formerr\n  [`\u003cFieldErr\u003e`]:                        #fielderr\n[Controllers]:                           #controllers\n  [`formController`]:                    #formcontroller\n[Advanced Concepts]:                     #advanced-concepts\n  [Svelte Bound Variables]:              #svelte-bound-variables\n  [more when `initialValue` in use ...]: #more-when-initialvalue-in-use-\n[Customization]:                         #customization\n  [Error Look and Feel]:                 #error-look-and-feel\n[Competition]:                           #competition\n\n\u003c!--- external links ---\u003e \n[svelte]:                   https://svelte.dev/\n[\"made with svelte\"]:       https://madewithsvelte.com/form\n[HTML5 Form Validation]:    https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation\n[HTML5's Form Validation]:  https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkevinast%2Fsvelte-native-forms","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkevinast%2Fsvelte-native-forms","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkevinast%2Fsvelte-native-forms/lists"}