From 751a2b1b647f90c4a47df92901bed3b4fb9bbcff Mon Sep 17 00:00:00 2001 From: Isaiah Thomason <47364027+ITenthusiasm@users.noreply.github.com> Date: Sat, 13 Apr 2024 11:41:24 -0400 Subject: [PATCH] chore: Update Documentation for the `FormValidityObserver` Note: We technically have not yet updated the types for the JS framework integrations, so we aren't 100% sure that our docs in that area are correct yet. But we're pretty confident that the documentation should be correct. After reviewing these docs on GitHub and verifying that we didn't break any links, we'll follow up with the integration TypeScript changes (and any docs updates that should be done as a result). --- docs/extras/philosophy.md | 2 +- docs/form-validity-observer/README.md | 40 +++++--- .../integrations/README.md | 98 +++++++++++-------- .../integrations/preact.md | 12 +-- .../integrations/react.md | 14 +-- .../integrations/solid.md | 12 +-- .../integrations/svelte.md | 12 +-- .../integrations/vue.md | 12 +-- docs/form-validity-observer/types.md | 59 ++++++----- packages/core/FormValidityObserver.d.ts | 4 +- packages/core/FormValidityObserver.js | 4 +- .../__tests__/FormValidityObserver.test.ts | 22 ++--- 12 files changed, 164 insertions(+), 127 deletions(-) diff --git a/docs/extras/philosophy.md b/docs/extras/philosophy.md index 5c257b0..4f4977c 100644 --- a/docs/extras/philosophy.md +++ b/docs/extras/philosophy.md @@ -318,7 +318,7 @@ The next natural step is to provide a way to validate an _entire form_. For that If the developer opts out of accessible error messaging, the `setFieldError` and `clearFieldError` methods will fallback to `field.setCustomValidity()`, and `validateField({ focus: true })`/`validateFields({ focus: true })` will fallback to `field.reportValidity()`/`form.reportValidity()`. -As an added bonus, the `FormValidityObserver` exposes a [`configure`](../form-validity-observer/README.md#method-formvalidityobserverconfigureename-string-errormessages-validationerrorsm-e-void) method that enables developers to configure the error messages that should be displayed when a field fails validation. (Any unconfigured error messages will fallback to the `validationMessage` that the browser provides.) It also allows a custom validation function to be configured for the field. +As an added bonus, the `FormValidityObserver` exposes a [`configure`](../form-validity-observer/README.md#method-formvalidityobserverconfigureename-string-errormessages-validationerrorsm-e-r-void) method that enables developers to configure the error messages that should be displayed when a field fails validation. (Any unconfigured error messages will fallback to the `validationMessage` that the browser provides.) It also allows a custom validation function to be configured for the field. Seeing the big picture here? The `FormValidityObserver` is basically a wrapper for the browser's native features when accessible error messages aren't being used. When accessible error messages are needed, it functions as an _enhancement_ (not a replacement) of the browser's features to satisfy that need. As a bonus, it includes configurable scrolling/rendering functionality as well. diff --git a/docs/form-validity-observer/README.md b/docs/form-validity-observer/README.md index 75dd96b..9fa9688 100644 --- a/docs/form-validity-observer/README.md +++ b/docs/form-validity-observer/README.md @@ -107,19 +107,30 @@ The `FormValidityObserver()` constructor creates a new observer and configures i
renderer: (errorContainer: HTMLElement, errorMessage: M | null) => void

- The function used to render error messages to the DOM when a validation constraint's render option is true or when FormValidityObserver.setFieldError() is called with the render=true option. (See the ValidationErrors type for more details about validation constraints.) When a field becomes valid (or when FormValidityObserver.clearFieldError() is called), this function will be called with null if the field has an accessible error container. + The function used to render error messages (typically to the DOM) when a validation constraint's render option is true or when FormValidityObserver.setFieldError() is called with the render=true option. (See the ValidationErrors type for more details about validation constraints.) When a field becomes valid (or when FormValidityObserver.clearFieldError() is called), this function will be called with null. Note that this function will only be called if the field has an accessible error container.

- The message type, M is determined from your function definition. The type can be anything (e.g., a string, an object, a ReactElement, or anything else). + The Message Type, M, is determined from your function definition. The type can be anything (e.g., a string, an object, a ReactElement, or anything else).

The renderer defaults to a function that accepts error messages of type string and renders them to the DOM as raw HTML.

-
defaultErrors: ValidationErrors<M, E>
+
renderByDefault: R extends boolean

- Configures the default error messages to display for the validation constraints. (See the configure method for more details about error message configuration, and refer to the ValidationErrors type for more details about validation constraints.) + Determines the default value for every validation constraint's render option. (Also sets the default value for FormValidityObserver.setFieldError's render option.) +

+

+

+ Note: When renderByDefault is true, the renderer function must account for error messages of type string. (The default renderer function already accounts for this.) So, for example, if you wanted your renderer function to support ReactElements, and the renderByDefault option was true, then your renderer's Message Type, M, would need to be ReactElement | string. +
+

+
+
defaultErrors: ValidationErrors<M, E, R>
+
+

+ Configures the default error messages to display for the validation constraints. (See the configure method for more details about error message configuration, and refer to the ValidationErrors type for more details about validation constraints.)

@@ -158,7 +169,7 @@ const observer = new FormValidityObserver("focusout", { ### Method: `FormValidityObserver.observe(form: HTMLFormElement): boolean` -Instructs the observer to validate any fields (belonging to the provided form) that a user interacts with, and registers the observer's validation functions with the provided form. Automatic field validation will only occur when a field belonging to the form emits an event matching one of the `types` that were specified during the observer's construction. Unlike the `FormObserver` and the `FormStorageObserver`, _the `FormValidityObserver` may only observe 1 form at a time_. +Instructs the observer to validate any fields (belonging to the provided form) that a user interacts with, and registers the observer's validation methods with the provided form. Automatic field validation will only occur when a field belonging to the form emits an event matching one of the `types` that were specified during the observer's construction. Unlike the `FormObserver` and the `FormStorageObserver`, _the `FormValidityObserver` may only observe 1 form at a time_. Note that the `name` attribute is what the observer uses to [identify fields](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormControlsCollection/namedItem) during manual form validation and error handling. Therefore, a valid `name` is required for all validated fields. **If a field does not have a `name`, then it _will not_ participate in form validation.** Since the [web specification](https://www.w3.org/TR/html401/interact/forms.html#successful-controls) does not allow nameless fields to participate in form submission, this is likely a requirement that your application already satisfies. @@ -178,7 +189,7 @@ form.elements[0].dispatchEvent(new InputEvent("input")); // Field gets validated ### Method: `FormValidityObserver.unobserve(form: HTMLFormElement): boolean` -Instructs the observer to stop watching a form for user interactions. The form's fields will no longer be validated when a user interacts with them, and the observer's manual validation functions will be disabled. +Instructs the observer to stop watching a form for user interactions. The form's fields will no longer be validated when a user interacts with them, and the observer's manual validation methods will be disabled. If the provided form element was being watched before `unobserve()` was called, the method will run any necessary teardown logic and return `true`. Otherwise, the method does nothing and returns `false`. @@ -213,7 +224,7 @@ observer.unobserve(form); // Returns `false` because the form was already `unobs form1.elements[0].dispatchEvent(new FocusEvent("focusout")); // Does nothing ``` -### Method: `FormValidityObserver.configure(name: string, errorMessages: `[`ValidationErrors`](./types.md#validationerrorsm-e)`): void` +### Method: `FormValidityObserver.configure(name: string, errorMessages: `[`ValidationErrors`](./types.md#validationerrorsm-e-r)`): void` Configures the error messages that will be displayed for a form field's validation constraints. If an error message is not configured for a validation constraint and there is no corresponding [default configuration](#form-validity-observer-options-default-errors), then the field's [`validationMessage`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validationMessage) will be used instead. For [native form fields](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/elements), the browser automatically supplies a default `validationMessage` depending on the broken constraint. @@ -265,7 +276,7 @@ creditCardField.dispatchEvent(new FocusEvent("focusout")); ### Method: `FormValidityObserver.validateFields(options?: ValidateFieldsOptions): boolean | Promise` -Validates all of the observed form's fields, returning `true` if _all_ of the validated fields pass validation and `false` otherwise. The `boolean` that `validateFields()` returns will be wrapped in a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) if _any_ of the validated fields use an asynchronous function for the [`validate` constraint](./types.md#validationerrorsm-e). This promise will `resolve` after all asynchronous validation functions have `settled`. +Validates all of the observed form's fields, returning `true` if _all_ of the validated fields pass validation and `false` otherwise. The `boolean` that `validateFields()` returns will be wrapped in a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) if _any_ of the validated fields use an asynchronous function for the [`validate` constraint](./types.md#validationerrorsm-e-r). This promise will `resolve` after all asynchronous validation functions have `settled`. #### Parameters @@ -282,7 +293,7 @@ When the `focus` option is `false`, you can consider `validateFields()` to be an ### Method: `FormValidityObserver.validateField(name: string, options?: ValidateFieldOptions): boolean | Promise` -Validates the form field with the specified `name`, returning `true` if the field passes validation and `false` otherwise. The `boolean` that `validateField()` returns will be wrapped in a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) if the field's [`validate` constraint](./types.md#validationerrorsm-e) runs asynchronously. This promise will `resolve` after the asynchronous validation function `resolves`. Unlike the [`validateFields()`](#method-formvalidityobservervalidatefieldsoptions-validatefieldsoptions-boolean--promiseboolean) method, this promise will also `reject` if the asynchronous validation function `rejects`. +Validates the form field with the specified `name`, returning `true` if the field passes validation and `false` otherwise. The `boolean` that `validateField()` returns will be wrapped in a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) if the field's [`validate` constraint](./types.md#validationerrorsm-e-r) runs asynchronously. This promise will `resolve` after the asynchronous validation function `resolves`. Unlike the [`validateFields()`](#method-formvalidityobservervalidatefieldsoptions-validatefieldsoptions-boolean--promiseboolean) method, this promise will also `reject` if the asynchronous validation function `rejects`. > Note: Per the HTML spec, any field whose [`willValidate`](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/willValidate) property is `false` will automatically pass validation. @@ -326,10 +337,10 @@ The Field Element Type, `E`, represents the invalid form field. This type is inf
render (Optional)

- Indicates that the field's error message should be rendered to the DOM using the observer's renderer function. Defaults to false. + Indicates that the field's error message should be rendered using the observer's renderer function. Defaults to the value of the observer's renderByDefault configuration option.

- When the render argument is false (or omitted), then the error message must be of type string. When render is true, then the error message must be of type M, where M is determined from the observer's renderer function. + When the render argument is false, then the error message must be of type string. When render is true, then the error message must be of type M, where M is determined from the observer's renderer function.

@@ -337,7 +348,8 @@ The Field Element Type, `E`, represents the invalid form field. This type is inf **Example** ```js -const observer = new FormValidityObserver("change"); // By default, the `renderer` renders strings as raw HTML +// By default, the `renderer` renders strings as raw HTML, and the `renderByDefault` option is `false` +const observer = new FormValidityObserver("change"); const form = document.getElementById("my-form"); observer.observe(form); @@ -376,7 +388,7 @@ The idea here is to make form validation as quick and easy as possible for those
Justification -If your forms are [progressively enhanced](https://learn.svelte.dev/tutorial/progressive-enhancement), you will already be satisfying this requirement. Leveraging the `name` attribute enables users who lack access to JavaScript to use your forms. Moreover, the `name` attribute enables many well-known form-related tools to identify fields without causing friction with developers. Given these realities, this restriction seems reasonable to us. +If your forms are [progressively enhanced](https://learn.svelte.dev/tutorial/progressive-enhancement), you will already be satisfying this requirement. Leveraging the `name` attribute enables users who lack access to JavaScript to use your forms. Moreover, the `name` attribute enables many well-known form-related tools to identify fields without causing friction for developers. Given these realities, this restriction seems reasonable to us.
@@ -404,7 +416,7 @@ If your forms provide [accessible radio button groups](https://www.w3.org/WAI/tu ## What about `aria-errormessage`? -If you're familiar with the [`aria-errormessage`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-errormessage) attribute, then you'll know that it is technically "better" than the [`aria-describedby`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-describedby) attribute when it comes to conveying error messages for invalid form fields. Although it is technically superior, the `aria-errormessage` attribute is also [far less supported](https://a11ysupport.io/tech/aria/aria-errormessage_attribute) by assistive technologies (as of 2023-10-27). Because the `aria-describedby` attribute is [accepted by the WAI](https://www.w3.org/WAI/WCAG21/Techniques/aria/ARIA21#example-2-identifying-errors-in-data-format) as a valid means to convey error messages for fields, and because the attribute is more widely supported by assistive technologies, the `FormValidityObserver` uses this attribute for conveying error messages instead. +If you're familiar with the [`aria-errormessage`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-errormessage) attribute, then you'll know that it is technically "better" than the [`aria-describedby`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-describedby) attribute when it comes to conveying error messages for invalid form fields. Although it is technically superior, the `aria-errormessage` attribute is also [far less supported](https://a11ysupport.io/tech/aria/aria-errormessage_attribute) by assistive technologies (as of 2024-04-13). Because the `aria-describedby` attribute is [accepted by the WAI](https://www.w3.org/WAI/WCAG21/Techniques/aria/ARIA21#example-2-identifying-errors-in-data-format) as a valid means to convey error messages for fields, and because the attribute is more widely supported by assistive technologies, the `FormValidityObserver` uses this attribute for conveying error messages instead. In the future, when `aria-errormessage` has better support, the `FormValidityObserver` will be updated to support it. Until then, the attribute will not be supported. diff --git a/docs/form-validity-observer/integrations/README.md b/docs/form-validity-observer/integrations/README.md index ba6db90..6f2344a 100644 --- a/docs/form-validity-observer/integrations/README.md +++ b/docs/form-validity-observer/integrations/README.md @@ -135,12 +135,14 @@ function createFormValidityObserver< T extends OneOrMany, M = string, E extends ValidatableField = ValidatableField, ->(types: T, options?: FormValidityObserverOptions): SvelteFormValidityObserver { - const observer = new FormValidityObserver(types, options) as unknown as SvelteFormValidityObserver; + R extends boolean = false, +>(types: T, options?: FormValidityObserverOptions): SvelteFormValidityObserver { + const observer = new FormValidityObserver(types, options) as unknown as SvelteFormValidityObserver; return observer; } -interface SvelteFormValidityObserver extends Omit, "configure"> {} +interface SvelteFormValidityObserver + extends Omit, "configure"> {} ``` Note: Since we will be augmenting the `FormValidityObserver.configure()` method, we are _not_ copying its type definition to the `SvelteFormValidityObserver` interface. @@ -162,8 +164,9 @@ function createFormValidityObserver< T extends OneOrMany, M = string, E extends ValidatableField = ValidatableField, ->(types: T, options?: FormValidityObserverOptions): SvelteFormValidityObserver { - const observer = new FormValidityObserver(types, options) as unknown as SvelteFormValidityObserver; + R extends boolean = false, +>(types: T, options?: FormValidityObserverOptions): SvelteFormValidityObserver { + const observer = new FormValidityObserver(types, options) as unknown as SvelteFormValidityObserver; /* ---------- Bindings ---------- */ // Form Observer Methods @@ -180,7 +183,8 @@ function createFormValidityObserver< return observer; } -interface SvelteFormValidityObserver extends Omit, "configure"> {} +interface SvelteFormValidityObserver + extends Omit, "configure"> {} ``` Note: Because we will be enhancing the `configure` method, we _have not_ attached it to the `observer` object that we return. @@ -203,8 +207,9 @@ function createFormValidityObserver< T extends OneOrMany, M = string, E extends ValidatableField = ValidatableField, ->(types: T, options?: FormValidityObserverOptions): SvelteFormValidityObserver { - const observer = new FormValidityObserver(types, options) as unknown as SvelteFormValidityObserver; + R extends boolean = false, +>(types: T, options?: FormValidityObserverOptions): SvelteFormValidityObserver { + const observer = new FormValidityObserver(types, options) as unknown as SvelteFormValidityObserver; /* ---------- Bindings ---------- */ // Apply all bindings... @@ -224,7 +229,8 @@ function createFormValidityObserver< return observer; } -interface SvelteFormValidityObserver extends Omit, "configure"> { +interface SvelteFormValidityObserver + extends Omit, "configure"> { autoObserve(form: HTMLFormElement, novalidate?: boolean): ActionReturn; } ``` @@ -284,7 +290,7 @@ The benefit of this approach, as we mentioned earlier, is that our configuration ``` -Of course, as with the core `FormValidityObserver`, calls to `configure` can be skipped if the developer is _only_ using the browser's default error messages: +Of course, as with the core `FormValidityObserver`, calls to `configure` can be skipped if the developer is _only_ using the using the configured [`defaultErrors`](../README.md#form-validity-observer-options-default-errors) and/or the browser's default error messages: ```html @@ -292,7 +298,7 @@ Of course, as with the core `FormValidityObserver`, calls to `configure` can be Note: Our `configure` method should _not_ support adding an error `message` for a constraint without the constraint's `value`. This is because the error message would never get used in that scenario. -Now that we've specified all the requirements, let's implement this functionality. First off, we'll update the `SvelteFormValidityObserver` interface. Some new TypeScript types will have to be added here. If you're only using JavaScript, you can skip this part. :) +Now that we've specified all of the requirements, let's implement this functionality. First off, we'll update the `SvelteFormValidityObserver` interface. Some new TypeScript types will have to be added here. If you're only using JavaScript, you can skip this part. :) #### Adding the TypeScript Types for `configure` @@ -311,9 +317,10 @@ import type { HTMLInputAttributes } from "svelte/elements"; // Definition of `createFormValidityObserver` ... -interface SvelteFormValidityObserver extends Omit, "configure"> { +interface SvelteFormValidityObserver + extends Omit, "configure"> { // Augments `FormValidityObserver.configure()` - configure(name: string, errorMessages: SvelteValidationErrors): SvelteFieldProps; + configure(name: string, errorMessages: SvelteValidationErrors): SvelteFieldProps; autoObserve(form: HTMLFormElement, novalidate?: boolean): ActionReturn; } @@ -324,23 +331,30 @@ type SvelteFieldProps = Pick< >; // Augments `ValidationErrors` type -export interface SvelteValidationErrors - extends Pick, "badinput" | "validate"> { - required?: SvelteErrorDetails | ErrorMessage; - minlength?: SvelteErrorDetails; - min?: SvelteErrorDetails; - maxlength?: SvelteErrorDetails; - max?: SvelteErrorDetails; - step?: SvelteErrorDetails; - type?: SvelteErrorDetails; - pattern?: SvelteErrorDetails; +export interface SvelteValidationErrors + extends Pick, "badinput" | "validate"> { + required?: + | SvelteErrorDetails + | ErrorMessage; + minlength?: SvelteErrorDetails; + min?: SvelteErrorDetails; + maxlength?: SvelteErrorDetails; + max?: SvelteErrorDetails; + step?: SvelteErrorDetails; + type?: SvelteErrorDetails; + pattern?: SvelteErrorDetails; } // Augments `ErrorDetails` type -type SvelteErrorDetails = +type SvelteErrorDetails = | V - | { render: true; message: ErrorMessage; value: V } - | { render?: false; message: ErrorMessage; value: V }; + | (R extends true + ? + | { render?: true; message: ErrorMessage; value: V } + | { render: false; message: ErrorMessage; value: V } + : + | { render: true; message: ErrorMessage; value: V } + | { render?: false; message: ErrorMessage; value: V }); ``` You don't have to understand what these types do to use them. But if you're interested in understanding what's happening here, let's walk you through what we did. @@ -349,7 +363,7 @@ You don't have to understand what these types do to use them. But if you're inte Our `configure` method has changed the type of the `errorMessages` argument from `ValidationErrors` to `SvelteValidationErrors` so that we can configure a field's constraints and error messages simultaneously. The type that enables us to support this feature is `SvelteErrorDetails`. -`SvelteErrorDetails` is _almost_ the exact same type as [`ErrorDetails`](../types.md#errordetailsm-e). There are only two differences between `SvelteErrorDetail` and `ErrorDetails`: +`SvelteErrorDetails` is _almost_ the exact same type as [`ErrorDetails`](../types.md#errordetailsm-e-r). There are only two differences between `SvelteErrorDetails` and `ErrorDetails`:
  1. @@ -362,19 +376,19 @@ Our `configure` method has changed the type of the `errorMessages` argument from
  2. - When an object is not being used, SvelteErrorDetails details replaces ErrorMessage<string> with V, where V represents the value of the constraint. This is an alteration of the ErrorDetails type. + When an object is not being used, SvelteErrorDetails details replaces ErrorMessage with V, where V represents the value of the constraint. This is an alteration of the ErrorDetails type.

    - Whenever a raw value is used for SvelteErrorDetails, developers will be able to specify a field's constraint without providing the error message for that constraint. In this scenario, the browser's default error message will be used for that constraint instead. Since it does not make sense to provide an error message without a constraint value, the SvelteErrorDetails type does not support that "use case". + Whenever a raw value is used for SvelteErrorDetails, developers will be able to specify a field's constraint without providing the error message for that constraint. In this scenario, the browser's default error message (or the configured default error) will be used for that constraint instead. Since it does not make sense to provide an error message without a constraint value, the SvelteErrorDetails type does not support that "use case".

-Just as the `ErrorDetails` type forms the foundation of the [`ValidationErrors`](../types.md#validationerrorsm-e) type, so the `SvelteErrorDetails` type forms the foundation of the `SvelteValidationErrors` type. The type definition for `SvelteValidationErrors` is _almost_ the exact same as the type definition for `ValidationErrors`. In fact, the `badinput` and `validate` properties are exactly the same between the 2. +Just as the `ErrorDetails` type forms the foundation of the [`ValidationErrors`](../types.md#validationerrorsm-e-r) type, so the `SvelteErrorDetails` type forms the foundation of the `SvelteValidationErrors` type. The type definition for `SvelteValidationErrors` is _almost_ the exact same as the type definition for `ValidationErrors`. In fact, the `badinput` and `validate` properties are exactly the same between the 2. The primary way in which the `SvelteValidationErrors` type differs from the `ValidationErrors` type is that it takes constraint values into account (with the help of `SvelteErrorDetails`). It determines the value types that each constraint supports by looking at `Svelte`'s type definition for the `input` field's props (i.e., `HTMLInputAttributes`). (**Note: If you're using a different JS framework, you should use _that_ framework's type definitions for the `input` field's props instead.**) -Notice that the `required` constraint is slightly different from the others in that it supports one additional type: [`ErrorMessage`](../types.md#errormessagem-e). If the developer supplies an error message by itself for the `required` constraint, it is safe to assume that `required` is `true`. This is an assumption that can only be made safely with the `required` constraint because it is a `boolean`. +Notice that the `required` constraint is slightly different from the others in that it supports one additional type: [`ErrorMessage`](../types.md#errormessagem-e). If the developer supplies an error message by itself for the `required` constraint, it is safe to assume that `required` is `true`. This is an assumption that can only be made safely with the `required` constraint because it is a `boolean`. ##### Enhancing the Return Type of `configure` @@ -390,8 +404,9 @@ type SvelteFieldProps = Pick< And we make _this_ the return type of `configure`: ```ts -interface SvelteFormValidityObserver extends Omit, "configure"> { - configure(name: string, errorMessages: SvelteValidationErrors): SvelteFieldProps; +interface SvelteFormValidityObserver + extends Omit, "configure"> { + configure(name: string, errorMessages: SvelteValidationErrors): SvelteFieldProps; autoObserve(form: HTMLFormElement, novalidate?: boolean): ActionReturn; } ``` @@ -409,23 +424,24 @@ export default function createFormValidityObserver< T extends OneOrMany, M = string, E extends ValidatableField = ValidatableField, ->(types: T, options?: FormValidityObserverOptions): SvelteFormValidityObserver { - const observer = new FormValidityObserver(types, options) as unknown as SvelteFormValidityObserver; + R extends boolean = false, +>(types: T, options?: FormValidityObserverOptions): SvelteFormValidityObserver { + const observer = new FormValidityObserver(types, options) as unknown as SvelteFormValidityObserver; /* ---------- Bindings ---------- */ // Apply bindings for exposed methods ... /** **Private** reference to the original {@link FormValidityObserver.configure} method */ - const originalConfigure = observer.configure.bind(observer) as FormValidityObserver["configure"]; + const originalConfigure = observer.configure.bind(observer) as FormValidityObserver["configure"]; /* ---------- Enhancements ---------- */ // Definition for `autoObserver` ... // Enhanced `configure` method observer.configure = (name, errorMessages) => { - const keys = Object.keys(errorMessages) as Array>; + const keys = Object.keys(errorMessages) as Array>; const props = { name } as SvelteFieldProps; - const config = {} as ValidationErrors; + const config = {} as ValidationErrors; // Build `props` object and error `config` object from `errorMessages` for (let i = 0; i < keys.length; i++) { @@ -474,7 +490,7 @@ Here in `configure`, we're looping over each of the properties provided in the ` 1. If the constraint _value_ is `null` or `undefined`, then the constraint was omitted by the developer. There is nothing to add to the local error `config` or the returned constraint `props`. A `required` constraint with a value of `false` is treated as if it was `undefined`. 2. If the _constraint_ is `badinput` or `validate`, it can be copied directly to the error `config`. There are no `props` to update here since `badinput` and `validate` are not valid HTML attributes. -3. If the constraint _value_ is not an object, then we can assume that we have a raw constraint value. (For instance, we could have a raw `number` value for the `max` constraint.) The developer has indicated that they want to specify a field constraint without a custom error message; so only the constraint `props` are updated.

The exception to this rule is the `required` constraint. If the _constraint_ is `required` **and** the constraint _value_ is an `ErrorMessage`, then we assign this value to the error `config` instead of the `props` object. In this scenario, the _value_ for the `required` constraint is implicitly `true` (even if the value is an empty string).

+3. If the constraint _value_ is not a `SvelteErrorDetails` object, then we can assume that we have a raw constraint value. (For instance, we could have a raw `number` value for the `max` constraint.) The developer has indicated that they want to specify a field constraint without a custom error message; so only the constraint `props` are updated.

The exception to this rule is the `required` constraint. If the _constraint_ is `required` **and** the constraint _value_ is an `ErrorMessage`, then we assign this value to the error `config` instead of the `props` object. In this scenario, the _value_ for the `required` constraint is implicitly `true` (even if the value is an empty string).

4. If the constraint _value_ is an object, then we can give the `value` property on this object to the `props` object. For simplicity, the error `config` can be given the entire constraint object in this scenario, even though it won't use the attached `value` property. Notice also that here, yet again, a `required` constraint with a value of `false` is treated as if the constraint was `undefined`. After we finish looping over the properties in `errorMessages`, we configure the error messages for the field by calling the _core_ `FormValidityObserver.configure()` method with the error `config` object. Finally, we return any necessary form field `props`. @@ -516,9 +532,9 @@ If we want to keep our code readable, then the next best solution is to use `any ```ts observer.configure = (name, errorMessages) => { - const keys = Object.keys(errorMessages) as Array>; + const keys = Object.keys(errorMessages) as Array>; const props = { name } as SvelteFieldProps; - const config = {} as ValidationErrors; + const config = {} as ValidationErrors; // Build `props` object and error `config` object from `errorMessages` for (let i = 0; i < keys.length; i++) { diff --git a/docs/form-validity-observer/integrations/preact.md b/docs/form-validity-observer/integrations/preact.md index ac6466f..7321dd0 100644 --- a/docs/form-validity-observer/integrations/preact.md +++ b/docs/form-validity-observer/integrations/preact.md @@ -6,9 +6,9 @@ A _convenience_ API for reducing code repetition in a [Preact](https://preactjs. Creates an enhanced version of the `FormValidityObserver`, known as the `PreactFormValidityObserver`. It accepts the exact same arguments as the [`FormValidityObserver`'s constructor](../README.md#constructor-formvalidityobservertypes-options). -### Return Type: `PreactFormValidityObserver` +### Return Type: `PreactFormValidityObserver` -An enhanced version of the `FormValidityObserver`, designed specifically for Preact applications. It has the same Type Parameters as the `FormValidityObserver`. As with the `FormValidityObserver`, the type of `M` is derived from the [`renderer`](../README.md#form-validity-observer-options-renderer) option. +An enhanced version of the `FormValidityObserver`, designed specifically for Preact applications. It has the same Type Parameters as the `FormValidityObserver`. As with the `FormValidityObserver`, the type of `M` is derived from the [`renderer`](../README.md#form-validity-observer-options-renderer) option, and the type of `R` is derived from the [`renderByDefault`](../README.md#form-validity-observer-options-render-by-default) option. #### Copied Methods @@ -77,13 +77,13 @@ class MyFormClass extends Component { Remember that `autoObserve` is simply a convenience utility for calling `observe` and `unobserve` automatically. You're free to setup and teardown the `FormValidityObserver` manually if you prefer. -#### Function: `configure(name: string, errorMessages: PreactValidationErrors): PreactFieldProps` +#### Function: `configure(name: string, errorMessages: PreactValidationErrors): PreactFieldProps` -An enhanced version of [`FormValidityObserver.configure`](../README.md#method-formvalidityobserverconfigureename-string-errormessages-validationerrorsm-e-void) for `Preact`. In addition to configuring a field's error messages, it generates the props that should be applied to the field based on the provided arguments. +An enhanced version of [`FormValidityObserver.configure`](../README.md#method-formvalidityobserverconfigureename-string-errormessages-validationerrorsm-e-r-void) for `Preact`. In addition to configuring a field's error messages, it generates the props that should be applied to the field based on the provided arguments. > Note: If the field is _only_ using the configured [`defaultErrors`](../README.md#form-validity-observer-options-default-errors) and/or the browser's default error messages, it _does not_ need to be `configure`d. -The `PreactValidationErrors` type is an enhanced version of the core [`ValidationErrors`](../types.md#validationerrorsm-e) type. Here is how `PreactValidationErrors` compares to `ValidationErrors`. +The `PreactValidationErrors` type is an enhanced version of the core [`ValidationErrors`](../types.md#validationerrorsm-e-r) type. Here is how `PreactValidationErrors` compares to `ValidationErrors`. ##### Properties That Mimic the `ValidationErrors` Properties @@ -139,7 +139,7 @@ All the other properties on the `PreactValidationErrors` type are enhancements o The rules are as follows: -1) When a constraint is configured with an [`ErrorDetails`](../types.md#errordetailsm-e) object, the object must include a `value` property specifying the value of the constraint. In this scenario, both the field's constraint value _and_ its error message are configured. +1) When a constraint is configured with an [`ErrorDetails`](../types.md#errordetailsm-e-r) object, the object must include a `value` property specifying the value of the constraint. In this scenario, both the field's constraint value _and_ its error message are configured. ```tsx import { createFormValidityObserver } from "@form-observer/preact"; diff --git a/docs/form-validity-observer/integrations/react.md b/docs/form-validity-observer/integrations/react.md index db21d55..f1c46b9 100644 --- a/docs/form-validity-observer/integrations/react.md +++ b/docs/form-validity-observer/integrations/react.md @@ -17,9 +17,9 @@ Creates an enhanced version of the `FormValidityObserver`, known as the `ReactFo This function acts as the foundation for the [`useFormValidityObserver`](#custom-hook-useformvalidityobservertypes-options) hook. For those using class components, you can use `createFormValidityObserver` directly. -### Return Type: `ReactFormValidityObserver` +### Return Type: `ReactFormValidityObserver` -An enhanced version of the `FormValidityObserver`, designed specifically for React applications. It has the same Type Parameters as the `FormValidityObserver`. As with the `FormValidityObserver`, the type of `M` is derived from the [`renderer`](../README.md#form-validity-observer-options-renderer) option. +An enhanced version of the `FormValidityObserver`, designed specifically for React applications. It has the same Type Parameters as the `FormValidityObserver`. As with the `FormValidityObserver`, the type of `M` is derived from the [`renderer`](../README.md#form-validity-observer-options-renderer) option, and the type of `R` is derived from the [`renderByDefault`](../README.md#form-validity-observer-options-render-by-default) option. #### Copied Methods @@ -63,7 +63,7 @@ class MyFormClass extends Component { } ``` -Due to React's unique re-rendering system, if you're using the `autoObserve` utility in a component that is expected to re-render, then you might need to memoize its returned `ref` callback to have consistent results. In functional components, you can memoize the callback with `useMemo` (or `useCallback`). In class components, you can effectively "memoize" the callback by assigning it to the class instance during its instantiation. +Due to React's unique re-rendering model, if you're using the `autoObserve` utility in a component that is expected to re-render, then you might need to memoize its returned `ref` callback to have consistent results. In functional components, you can memoize the callback with `useMemo` (or `useCallback`). In class components, you can effectively "memoize" the callback by assigning it to the class instance during its instantiation. ```tsx import { useMemo, Component } from "react"; @@ -87,13 +87,13 @@ class MyFormClass extends Component { Remember that `autoObserve` is simply a convenience utility for calling `observe` and `unobserve` automatically. You're free to setup and teardown the `FormValidityObserver` manually if you prefer. -#### Function: `configure(name: string, errorMessages: ReactValidationErrors): ReactFieldProps` +#### Function: `configure(name: string, errorMessages: ReactValidationErrors): ReactFieldProps` -An enhanced version of [`FormValidityObserver.configure`](../README.md#method-formvalidityobserverconfigureename-string-errormessages-validationerrorsm-e-void) for `React`. In addition to configuring a field's error messages, it generates the props that should be applied to the field based on the provided arguments. +An enhanced version of [`FormValidityObserver.configure`](../README.md#method-formvalidityobserverconfigureename-string-errormessages-validationerrorsm-e-r-void) for `React`. In addition to configuring a field's error messages, it generates the props that should be applied to the field based on the provided arguments. > Note: If the field is _only_ using the configured [`defaultErrors`](../README.md#form-validity-observer-options-default-errors) and/or the browser's default error messages, it _does not_ need to be `configure`d. -The `ReactValidationErrors` type is an enhanced version of the core [`ValidationErrors`](../types.md#validationerrorsm-e) type. Here is how `ReactValidationErrors` compares to `ValidationErrors`. +The `ReactValidationErrors` type is an enhanced version of the core [`ValidationErrors`](../types.md#validationerrorsm-e-r) type. Here is how `ReactValidationErrors` compares to `ValidationErrors`. ##### Properties That Mimic the `ValidationErrors` Properties @@ -149,7 +149,7 @@ All the other properties on the `ReactValidationErrors` type are enhancements of The rules are as follows: -1) When a constraint is configured with an [`ErrorDetails`](../types.md#errordetailsm-e) object, the object must include a `value` property specifying the value of the constraint. In this scenario, both the field's constraint value _and_ its error message are configured. +1) When a constraint is configured with an [`ErrorDetails`](../types.md#errordetailsm-e-r) object, the object must include a `value` property specifying the value of the constraint. In this scenario, both the field's constraint value _and_ its error message are configured. ```tsx import { createFormValidityObserver } from "@form-observer/react"; diff --git a/docs/form-validity-observer/integrations/solid.md b/docs/form-validity-observer/integrations/solid.md index 90f3487..7086ee5 100644 --- a/docs/form-validity-observer/integrations/solid.md +++ b/docs/form-validity-observer/integrations/solid.md @@ -6,9 +6,9 @@ A _convenience_ API for reducing code repetition in a [Solid](https://www.solidj Creates an enhanced version of the `FormValidityObserver`, known as the `SolidFormValidityObserver`. It accepts the exact same arguments as the [`FormValidityObserver`'s constructor](../README.md#constructor-formvalidityobservertypes-options). -### Return Type: `SolidFormValidityObserver` +### Return Type: `SolidFormValidityObserver` -An enhanced version of the `FormValidityObserver`, designed specifically for Solid applications. It has the same Type Parameters as the `FormValidityObserver`. As with the `FormValidityObserver`, the type of `M` is derived from the [`renderer`](../README.md#form-validity-observer-options-renderer) option. +An enhanced version of the `FormValidityObserver`, designed specifically for Solid applications. It has the same Type Parameters as the `FormValidityObserver`. As with the `FormValidityObserver`, the type of `M` is derived from the [`renderer`](../README.md#form-validity-observer-options-renderer) option, and the type of `R` is derived from the [`renderByDefault`](../README.md#form-validity-observer-options-render-by-default) option. #### Copied Methods @@ -45,13 +45,13 @@ function MyForm() { Remember that `autoObserve` is simply a convenience utility for calling `observe` and `unobserve` automatically. You're free to setup and teardown the `FormValidityObserver` manually if you prefer. -#### Function: `configure(name: string, errorMessages: SolidValidationErrors): SolidFieldProps` +#### Function: `configure(name: string, errorMessages: SolidValidationErrors): SolidFieldProps` -An enhanced version of [`FormValidityObserver.configure`](../README.md#method-formvalidityobserverconfigureename-string-errormessages-validationerrorsm-e-void) for `Solid`. In addition to configuring a field's error messages, it generates the props that should be applied to the field based on the provided arguments. +An enhanced version of [`FormValidityObserver.configure`](../README.md#method-formvalidityobserverconfigureename-string-errormessages-validationerrorsm-e-r-void) for `Solid`. In addition to configuring a field's error messages, it generates the props that should be applied to the field based on the provided arguments. > Note: If the field is _only_ using the configured [`defaultErrors`](../README.md#form-validity-observer-options-default-errors) and/or the browser's default error messages, it _does not_ need to be `configure`d. -The `SolidValidationErrors` type is an enhanced version of the core [`ValidationErrors`](../types.md#validationerrorsm-e) type. Here is how `SolidValidationErrors` compares to `ValidationErrors`. +The `SolidValidationErrors` type is an enhanced version of the core [`ValidationErrors`](../types.md#validationerrorsm-e-r) type. Here is how `SolidValidationErrors` compares to `ValidationErrors`. ##### Properties That Mimic the `ValidationErrors` Properties @@ -107,7 +107,7 @@ All the other properties on the `SolidValidationErrors` type are enhancements of The rules are as follows: -1) When a constraint is configured with an [`ErrorDetails`](../types.md#errordetailsm-e) object, the object must include a `value` property specifying the value of the constraint. In this scenario, both the field's constraint value _and_ its error message are configured. +1) When a constraint is configured with an [`ErrorDetails`](../types.md#errordetailsm-e-r) object, the object must include a `value` property specifying the value of the constraint. In this scenario, both the field's constraint value _and_ its error message are configured. ```tsx import { createFormValidityObserver } from "@form-observer/solid"; diff --git a/docs/form-validity-observer/integrations/svelte.md b/docs/form-validity-observer/integrations/svelte.md index a97b8cc..6218ed1 100644 --- a/docs/form-validity-observer/integrations/svelte.md +++ b/docs/form-validity-observer/integrations/svelte.md @@ -6,9 +6,9 @@ A _convenience_ API for reducing code repetition in a [Svelte](https://svelte.de Creates an enhanced version of the `FormValidityObserver`, known as the `SvelteFormValidityObserver`. It accepts the exact same arguments as the [`FormValidityObserver`'s constructor](../README.md#constructor-formvalidityobservertypes-options). -### Return Type: `SvelteFormValidityObserver` +### Return Type: `SvelteFormValidityObserver` -An enhanced version of the `FormValidityObserver`, designed specifically for Svelte applications. It has the same Type Parameters as the `FormValidityObserver`. As with the `FormValidityObserver`, the type of `M` is derived from the [`renderer`](../README.md#form-validity-observer-options-renderer) option. +An enhanced version of the `FormValidityObserver`, designed specifically for Svelte applications. It has the same Type Parameters as the `FormValidityObserver`. As with the `FormValidityObserver`, the type of `M` is derived from the [`renderer`](../README.md#form-validity-observer-options-renderer) option, and the type of `R` is derived from the [`renderByDefault`](../README.md#form-validity-observer-options-render-by-default) option. #### Copied Methods @@ -45,13 +45,13 @@ The `novalidate` parameter indicates that the [novalidate](https://developer.moz Remember that `autoObserve` is simply a convenience utility for calling `observe` and `unobserve` automatically. You're free to setup and teardown the `FormValidityObserver` manually if you prefer. -#### Function: `configure(name: string, errorMessages: SvelteValidationErrors): SvelteFieldProps` +#### Function: `configure(name: string, errorMessages: SvelteValidationErrors): SvelteFieldProps` -An enhanced version of [`FormValidityObserver.configure`](../README.md#method-formvalidityobserverconfigureename-string-errormessages-validationerrorsm-e-void) for `Svelte`. In addition to configuring a field's error messages, it generates the props that should be applied to the field based on the provided arguments. +An enhanced version of [`FormValidityObserver.configure`](../README.md#method-formvalidityobserverconfigureename-string-errormessages-validationerrorsm-e-r-void) for `Svelte`. In addition to configuring a field's error messages, it generates the props that should be applied to the field based on the provided arguments. > Note: If the field is _only_ using the configured [`defaultErrors`](../README.md#form-validity-observer-options-default-errors) and/or the browser's default error messages, it _does not_ need to be `configure`d. -The `SvelteValidationErrors` type is an enhanced version of the core [`ValidationErrors`](../types.md#validationerrorsm-e) type. Here is how `SvelteValidationErrors` compares to `ValidationErrors`. +The `SvelteValidationErrors` type is an enhanced version of the core [`ValidationErrors`](../types.md#validationerrorsm-e-r) type. Here is how `SvelteValidationErrors` compares to `ValidationErrors`. ##### Properties That Mimic the `ValidationErrors` Properties @@ -105,7 +105,7 @@ All the other properties on the `SvelteValidationErrors` type are enhancements o The rules are as follows: -1) When a constraint is configured with an [`ErrorDetails`](../types.md#errordetailsm-e) object, the object must include a `value` property specifying the value of the constraint. In this scenario, both the field's constraint value _and_ its error message are configured. +1) When a constraint is configured with an [`ErrorDetails`](../types.md#errordetailsm-e-r) object, the object must include a `value` property specifying the value of the constraint. In this scenario, both the field's constraint value _and_ its error message are configured. ```svelte
diff --git a/docs/form-validity-observer/integrations/vue.md b/docs/form-validity-observer/integrations/vue.md index 0963063..1d85a05 100644 --- a/docs/form-validity-observer/integrations/vue.md +++ b/docs/form-validity-observer/integrations/vue.md @@ -6,9 +6,9 @@ A _convenience_ API for reducing code repetition in a [Vue](https://vuejs.org/) Creates an enhanced version of the `FormValidityObserver`, known as the `VueFormValidityObserver`. It accepts the exact same arguments as the [`FormValidityObserver`'s constructor](../README.md#constructor-formvalidityobservertypes-options). -### Return Type: `VueFormValidityObserver` +### Return Type: `VueFormValidityObserver` -An enhanced version of the `FormValidityObserver`, designed specifically for Vue applications. It has the same Type Parameters as the `FormValidityObserver`. As with the `FormValidityObserver`, the type of `M` is derived from the [`renderer`](../README.md#form-validity-observer-options-renderer) option. +An enhanced version of the `FormValidityObserver`, designed specifically for Vue applications. It has the same Type Parameters as the `FormValidityObserver`. As with the `FormValidityObserver`, the type of `M` is derived from the [`renderer`](../README.md#form-validity-observer-options-renderer) option, and the type of `R` is derived from the [`renderByDefault`](../README.md#form-validity-observer-options-render-by-default) option. #### Copied Methods @@ -47,13 +47,13 @@ const { autoObserve } = createFormValidityObserver("focusout"); Remember that `autoObserve` is simply a convenience utility for calling `observe` and `unobserve` automatically. You're free to setup and teardown the `FormValidityObserver` manually if you prefer. -#### Function: `configure(name: string, errorMessages: VueValidationErrors): VueFieldProps` +#### Function: `configure(name: string, errorMessages: VueValidationErrors): VueFieldProps` -An enhanced version of [`FormValidityObserver.configure`](../README.md#method-formvalidityobserverconfigureename-string-errormessages-validationerrorsm-e-void) for `Vue`. In addition to configuring a field's error messages, it generates the props that should be applied to the field based on the provided arguments. +An enhanced version of [`FormValidityObserver.configure`](../README.md#method-formvalidityobserverconfigureename-string-errormessages-validationerrorsm-e-r-void) for `Vue`. In addition to configuring a field's error messages, it generates the props that should be applied to the field based on the provided arguments. > Note: If the field is _only_ using the configured [`defaultErrors`](../README.md#form-validity-observer-options-default-errors) and/or the browser's default error messages, it _does not_ need to be `configure`d. -The `VueValidationErrors` type is an enhanced version of the core [`ValidationErrors`](../types.md#validationerrorsm-e) type. Here is how `VueValidationErrors` compares to `ValidationErrors`. +The `VueValidationErrors` type is an enhanced version of the core [`ValidationErrors`](../types.md#validationerrorsm-e-r) type. Here is how `VueValidationErrors` compares to `ValidationErrors`. ##### Properties That Mimic the `ValidationErrors` Properties @@ -109,7 +109,7 @@ All the other properties on the `VueValidationErrors` type are enhancements of t The rules are as follows: -1) When a constraint is configured with an [`ErrorDetails`](../types.md#errordetailsm-e) object, the object must include a `value` property specifying the value of the constraint. In this scenario, both the field's constraint value _and_ its error message are configured. +1) When a constraint is configured with an [`ErrorDetails`](../types.md#errordetailsm-e-r) object, the object must include a `value` property specifying the value of the constraint. In this scenario, both the field's constraint value _and_ its error message are configured. ```vue