diff --git a/docs/framework/react/guides/listeners.md b/docs/framework/react/guides/listeners.md index 934ca6f3f..1f68d6a8c 100644 --- a/docs/framework/react/guides/listeners.md +++ b/docs/framework/react/guides/listeners.md @@ -67,3 +67,25 @@ function App() { ) } ``` + +### Built-in Debouncing + +If you are making an API request inside a listener, you may want to debounce the calls as it can lead to performance issues. +We enable an easy method for debouncing your listeners by adding a `onChangeDebounceMs` or `onBlurDebounceMs`. + +```tsx + { + console.log(`Country changed to: ${value} without a change within 500ms, resetting province`) + form.setFieldValue('province', '') + }, + }} +> + {(field) => ( + /* ... */ + )} + +``` diff --git a/docs/reference/classes/fieldapi.md b/docs/reference/classes/fieldapi.md index 34df8b000..93daf3c36 100644 --- a/docs/reference/classes/fieldapi.md +++ b/docs/reference/classes/fieldapi.md @@ -7,7 +7,7 @@ title: FieldApi # Class: FieldApi\ -Defined in: [packages/form-core/src/FieldApi.ts:842](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L842) +Defined in: [packages/form-core/src/FieldApi.ts:845](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L845) A class representing the API for managing a form field. @@ -65,7 +65,7 @@ the `new FieldApi` constructor. new FieldApi(opts): FieldApi ``` -Defined in: [packages/form-core/src/FieldApi.ts:970](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L970) +Defined in: [packages/form-core/src/FieldApi.ts:976](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L976) Initializes a new `FieldApi` instance. @@ -87,7 +87,7 @@ Initializes a new `FieldApi` instance. form: FormApi; ``` -Defined in: [packages/form-core/src/FieldApi.ts:886](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L886) +Defined in: [packages/form-core/src/FieldApi.ts:889](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L889) A reference to the form API instance. @@ -99,7 +99,7 @@ A reference to the form API instance. name: DeepKeys; ``` -Defined in: [packages/form-core/src/FieldApi.ts:910](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L910) +Defined in: [packages/form-core/src/FieldApi.ts:913](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L913) The field name. @@ -111,7 +111,7 @@ The field name. options: FieldApiOptions; ``` -Defined in: [packages/form-core/src/FieldApi.ts:914](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L914) +Defined in: [packages/form-core/src/FieldApi.ts:917](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L917) The field options. @@ -123,7 +123,7 @@ The field options. store: Derived>; ``` -Defined in: [packages/form-core/src/FieldApi.ts:938](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L938) +Defined in: [packages/form-core/src/FieldApi.ts:941](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L941) The field state store. @@ -132,10 +132,22 @@ The field state store. ### timeoutIds ```ts -timeoutIds: Record; +timeoutIds: object; ``` -Defined in: [packages/form-core/src/FieldApi.ts:965](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L965) +Defined in: [packages/form-core/src/FieldApi.ts:968](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L968) + +#### listeners + +```ts +listeners: Record; +``` + +#### validations + +```ts +validations: Record; +``` ## Accessors @@ -147,7 +159,7 @@ Defined in: [packages/form-core/src/FieldApi.ts:965](https://github.com/TanStack get state(): FieldState ``` -Defined in: [packages/form-core/src/FieldApi.ts:962](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L962) +Defined in: [packages/form-core/src/FieldApi.ts:965](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L965) The current field state. @@ -163,7 +175,7 @@ The current field state. getInfo(): FieldInfo ``` -Defined in: [packages/form-core/src/FieldApi.ts:1218](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1218) +Defined in: [packages/form-core/src/FieldApi.ts:1224](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1224) Gets the field information object. @@ -179,7 +191,7 @@ Gets the field information object. getMeta(): FieldMeta ``` -Defined in: [packages/form-core/src/FieldApi.ts:1186](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1186) +Defined in: [packages/form-core/src/FieldApi.ts:1192](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1192) #### Returns @@ -193,7 +205,7 @@ Defined in: [packages/form-core/src/FieldApi.ts:1186](https://github.com/TanStac getValue(): TData ``` -Defined in: [packages/form-core/src/FieldApi.ts:1168](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1168) +Defined in: [packages/form-core/src/FieldApi.ts:1177](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1177) Gets the current field value. @@ -213,7 +225,7 @@ Use `field.state.value` instead. handleBlur(): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1625](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1625) +Defined in: [packages/form-core/src/FieldApi.ts:1616](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1616) Handles the blur event. @@ -229,7 +241,7 @@ Handles the blur event. handleChange(updater): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1618](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1618) +Defined in: [packages/form-core/src/FieldApi.ts:1609](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1609) Handles the change event. @@ -254,7 +266,7 @@ insertValue( opts?): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1238](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1238) +Defined in: [packages/form-core/src/FieldApi.ts:1241](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1241) Inserts a value at the specified index, shifting the subsequent values to the right. @@ -284,7 +296,7 @@ Inserts a value at the specified index, shifting the subsequent values to the ri mount(): () => void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1063](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1063) +Defined in: [packages/form-core/src/FieldApi.ts:1072](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1072) Mounts the field instance to the form. @@ -307,7 +319,7 @@ moveValue( opts?): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1294](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1294) +Defined in: [packages/form-core/src/FieldApi.ts:1285](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1285) Moves the value at the first specified index to the second specified index. @@ -337,7 +349,7 @@ Moves the value at the first specified index to the second specified index. pushValue(value, opts?): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1223](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1223) +Defined in: [packages/form-core/src/FieldApi.ts:1229](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1229) Pushes a new value to the field. @@ -363,7 +375,7 @@ Pushes a new value to the field. removeValue(index, opts?): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1270](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1270) +Defined in: [packages/form-core/src/FieldApi.ts:1267](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1267) Removes a value at the specified index. @@ -422,7 +434,7 @@ Replaces a value at the specified index. setErrorMap(errorMap): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1645](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1645) +Defined in: [packages/form-core/src/FieldApi.ts:1633](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1633) Updates the field's errorMap @@ -444,7 +456,7 @@ Updates the field's errorMap setMeta(updater): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1191](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1191) +Defined in: [packages/form-core/src/FieldApi.ts:1197](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1197) Sets the field metadata. @@ -466,7 +478,7 @@ Sets the field metadata. setValue(updater, options?): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1175](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1175) +Defined in: [packages/form-core/src/FieldApi.ts:1184](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1184) Sets the field value and run the `change` validator. @@ -495,7 +507,7 @@ swapValues( opts?): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1282](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1282) +Defined in: [packages/form-core/src/FieldApi.ts:1276](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1276) Swaps the values at the specified indices. @@ -525,7 +537,7 @@ Swaps the values at the specified indices. update(opts): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1111](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1111) +Defined in: [packages/form-core/src/FieldApi.ts:1120](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1120) Updates the field instance with new options. @@ -547,7 +559,7 @@ Updates the field instance with new options. validate(cause, opts?): unknown[] | Promise ``` -Defined in: [packages/form-core/src/FieldApi.ts:1585](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1585) +Defined in: [packages/form-core/src/FieldApi.ts:1576](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1576) Validates the field value. diff --git a/docs/reference/interfaces/fieldapioptions.md b/docs/reference/interfaces/fieldapioptions.md index ced5f164b..8886296a0 100644 --- a/docs/reference/interfaces/fieldapioptions.md +++ b/docs/reference/interfaces/fieldapioptions.md @@ -7,7 +7,7 @@ title: FieldApiOptions # Interface: FieldApiOptions\ -Defined in: [packages/form-core/src/FieldApi.ts:446](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L446) +Defined in: [packages/form-core/src/FieldApi.ts:449](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L449) An object type representing the required options for the FieldApi class. @@ -63,7 +63,7 @@ An object type representing the required options for the FieldApi class. optional asyncAlways: boolean; ``` -Defined in: [packages/form-core/src/FieldApi.ts:393](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L393) +Defined in: [packages/form-core/src/FieldApi.ts:396](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L396) If `true`, always run async validation, even if there are errors emitted during synchronous validation. @@ -79,7 +79,7 @@ If `true`, always run async validation, even if there are errors emitted during optional asyncDebounceMs: number; ``` -Defined in: [packages/form-core/src/FieldApi.ts:389](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L389) +Defined in: [packages/form-core/src/FieldApi.ts:392](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L392) The default time to debounce async validation if there is not a more specific debounce time passed. @@ -95,7 +95,7 @@ The default time to debounce async validation if there is not a more specific de optional defaultMeta: Partial>; ``` -Defined in: [packages/form-core/src/FieldApi.ts:412](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L412) +Defined in: [packages/form-core/src/FieldApi.ts:415](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L415) An optional object with default metadata for the field. @@ -111,7 +111,7 @@ An optional object with default metadata for the field. optional defaultValue: NoInfer; ``` -Defined in: [packages/form-core/src/FieldApi.ts:385](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L385) +Defined in: [packages/form-core/src/FieldApi.ts:388](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L388) An optional default value for the field. @@ -127,7 +127,7 @@ An optional default value for the field. optional disableErrorFlat: boolean; ``` -Defined in: [packages/form-core/src/FieldApi.ts:440](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L440) +Defined in: [packages/form-core/src/FieldApi.ts:443](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L443) Disable the `flat(1)` operation on `field.errors`. This is useful if you want to keep the error structure as is. Not suggested for most use-cases. @@ -143,7 +143,7 @@ Disable the `flat(1)` operation on `field.errors`. This is useful if you want to form: FormApi; ``` -Defined in: [packages/form-core/src/FieldApi.ts:498](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L498) +Defined in: [packages/form-core/src/FieldApi.ts:501](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L501) *** @@ -153,7 +153,7 @@ Defined in: [packages/form-core/src/FieldApi.ts:498](https://github.com/TanStack optional listeners: FieldListeners; ``` -Defined in: [packages/form-core/src/FieldApi.ts:436](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L436) +Defined in: [packages/form-core/src/FieldApi.ts:439](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L439) A list of listeners which attach to the corresponding events @@ -169,7 +169,7 @@ A list of listeners which attach to the corresponding events name: TName; ``` -Defined in: [packages/form-core/src/FieldApi.ts:381](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L381) +Defined in: [packages/form-core/src/FieldApi.ts:384](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L384) The field name. The type will be `DeepKeys` to ensure your name is a deep key of the parent dataset. @@ -185,7 +185,7 @@ The field name. The type will be `DeepKeys` to ensure your name is optional validators: FieldValidators; ``` -Defined in: [packages/form-core/src/FieldApi.ts:397](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L397) +Defined in: [packages/form-core/src/FieldApi.ts:400](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L400) A list of validators to pass to the field diff --git a/docs/reference/interfaces/fieldlisteners.md b/docs/reference/interfaces/fieldlisteners.md index 7c64c8e01..277f98380 100644 --- a/docs/reference/interfaces/fieldlisteners.md +++ b/docs/reference/interfaces/fieldlisteners.md @@ -7,7 +7,7 @@ title: FieldListeners # Interface: FieldListeners\ -Defined in: [packages/form-core/src/FieldApi.ts:346](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L346) +Defined in: [packages/form-core/src/FieldApi.ts:347](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L347) ## Type Parameters @@ -25,7 +25,17 @@ Defined in: [packages/form-core/src/FieldApi.ts:346](https://github.com/TanStack optional onBlur: FieldListenerFn; ``` -Defined in: [packages/form-core/src/FieldApi.ts:352](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L352) +Defined in: [packages/form-core/src/FieldApi.ts:354](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L354) + +*** + +### onBlurDebounceMs? + +```ts +optional onBlurDebounceMs: number; +``` + +Defined in: [packages/form-core/src/FieldApi.ts:355](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L355) *** @@ -35,7 +45,17 @@ Defined in: [packages/form-core/src/FieldApi.ts:352](https://github.com/TanStack optional onChange: FieldListenerFn; ``` -Defined in: [packages/form-core/src/FieldApi.ts:351](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L351) +Defined in: [packages/form-core/src/FieldApi.ts:352](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L352) + +*** + +### onChangeDebounceMs? + +```ts +optional onChangeDebounceMs: number; +``` + +Defined in: [packages/form-core/src/FieldApi.ts:353](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L353) *** @@ -45,7 +65,7 @@ Defined in: [packages/form-core/src/FieldApi.ts:351](https://github.com/TanStack optional onMount: FieldListenerFn; ``` -Defined in: [packages/form-core/src/FieldApi.ts:353](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L353) +Defined in: [packages/form-core/src/FieldApi.ts:356](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L356) *** @@ -55,4 +75,4 @@ Defined in: [packages/form-core/src/FieldApi.ts:353](https://github.com/TanStack optional onSubmit: FieldListenerFn; ``` -Defined in: [packages/form-core/src/FieldApi.ts:354](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L354) +Defined in: [packages/form-core/src/FieldApi.ts:357](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L357) diff --git a/docs/reference/interfaces/fieldoptions.md b/docs/reference/interfaces/fieldoptions.md index a433202be..fbae41166 100644 --- a/docs/reference/interfaces/fieldoptions.md +++ b/docs/reference/interfaces/fieldoptions.md @@ -7,7 +7,7 @@ title: FieldOptions # Interface: FieldOptions\ -Defined in: [packages/form-core/src/FieldApi.ts:360](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L360) +Defined in: [packages/form-core/src/FieldApi.ts:363](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L363) An object type representing the options for a field in a form. @@ -45,7 +45,7 @@ An object type representing the options for a field in a form. optional asyncAlways: boolean; ``` -Defined in: [packages/form-core/src/FieldApi.ts:393](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L393) +Defined in: [packages/form-core/src/FieldApi.ts:396](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L396) If `true`, always run async validation, even if there are errors emitted during synchronous validation. @@ -57,7 +57,7 @@ If `true`, always run async validation, even if there are errors emitted during optional asyncDebounceMs: number; ``` -Defined in: [packages/form-core/src/FieldApi.ts:389](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L389) +Defined in: [packages/form-core/src/FieldApi.ts:392](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L392) The default time to debounce async validation if there is not a more specific debounce time passed. @@ -69,7 +69,7 @@ The default time to debounce async validation if there is not a more specific de optional defaultMeta: Partial>; ``` -Defined in: [packages/form-core/src/FieldApi.ts:412](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L412) +Defined in: [packages/form-core/src/FieldApi.ts:415](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L415) An optional object with default metadata for the field. @@ -81,7 +81,7 @@ An optional object with default metadata for the field. optional defaultValue: NoInfer; ``` -Defined in: [packages/form-core/src/FieldApi.ts:385](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L385) +Defined in: [packages/form-core/src/FieldApi.ts:388](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L388) An optional default value for the field. @@ -93,7 +93,7 @@ An optional default value for the field. optional disableErrorFlat: boolean; ``` -Defined in: [packages/form-core/src/FieldApi.ts:440](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L440) +Defined in: [packages/form-core/src/FieldApi.ts:443](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L443) Disable the `flat(1)` operation on `field.errors`. This is useful if you want to keep the error structure as is. Not suggested for most use-cases. @@ -105,7 +105,7 @@ Disable the `flat(1)` operation on `field.errors`. This is useful if you want to optional listeners: FieldListeners; ``` -Defined in: [packages/form-core/src/FieldApi.ts:436](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L436) +Defined in: [packages/form-core/src/FieldApi.ts:439](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L439) A list of listeners which attach to the corresponding events @@ -117,7 +117,7 @@ A list of listeners which attach to the corresponding events name: TName; ``` -Defined in: [packages/form-core/src/FieldApi.ts:381](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L381) +Defined in: [packages/form-core/src/FieldApi.ts:384](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L384) The field name. The type will be `DeepKeys` to ensure your name is a deep key of the parent dataset. @@ -129,6 +129,6 @@ The field name. The type will be `DeepKeys` to ensure your name is optional validators: FieldValidators; ``` -Defined in: [packages/form-core/src/FieldApi.ts:397](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L397) +Defined in: [packages/form-core/src/FieldApi.ts:400](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L400) A list of validators to pass to the field diff --git a/docs/reference/interfaces/fieldvalidators.md b/docs/reference/interfaces/fieldvalidators.md index 321e28081..bd82893e1 100644 --- a/docs/reference/interfaces/fieldvalidators.md +++ b/docs/reference/interfaces/fieldvalidators.md @@ -7,7 +7,7 @@ title: FieldValidators # Interface: FieldValidators\ -Defined in: [packages/form-core/src/FieldApi.ts:265](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L265) +Defined in: [packages/form-core/src/FieldApi.ts:266](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L266) ## Type Parameters @@ -39,7 +39,7 @@ Defined in: [packages/form-core/src/FieldApi.ts:265](https://github.com/TanStack optional onBlur: TOnBlur; ``` -Defined in: [packages/form-core/src/FieldApi.ts:314](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L314) +Defined in: [packages/form-core/src/FieldApi.ts:315](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L315) An optional function, that runs on the blur event of input. @@ -57,7 +57,7 @@ z.string().min(1) optional onBlurAsync: TOnBlurAsync; ``` -Defined in: [packages/form-core/src/FieldApi.ts:320](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L320) +Defined in: [packages/form-core/src/FieldApi.ts:321](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L321) An optional property similar to `onBlur` but async validation. @@ -75,7 +75,7 @@ z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) optional onBlurAsyncDebounceMs: number; ``` -Defined in: [packages/form-core/src/FieldApi.ts:327](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L327) +Defined in: [packages/form-core/src/FieldApi.ts:328](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L328) An optional number to represent how long the `onBlurAsync` should wait before running @@ -89,7 +89,7 @@ If set to a number larger than 0, will debounce the async validation event by th optional onBlurListenTo: DeepKeys[]; ``` -Defined in: [packages/form-core/src/FieldApi.ts:331](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L331) +Defined in: [packages/form-core/src/FieldApi.ts:332](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L332) An optional list of field names that should trigger this field's `onBlur` and `onBlurAsync` events when its value changes @@ -101,7 +101,7 @@ An optional list of field names that should trigger this field's `onBlur` and `o optional onChange: TOnChange; ``` -Defined in: [packages/form-core/src/FieldApi.ts:292](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L292) +Defined in: [packages/form-core/src/FieldApi.ts:293](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L293) An optional function, that runs on the change event of input. @@ -119,7 +119,7 @@ z.string().min(1) optional onChangeAsync: TOnChangeAsync; ``` -Defined in: [packages/form-core/src/FieldApi.ts:298](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L298) +Defined in: [packages/form-core/src/FieldApi.ts:299](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L299) An optional property similar to `onChange` but async validation @@ -137,7 +137,7 @@ z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) optional onChangeAsyncDebounceMs: number; ``` -Defined in: [packages/form-core/src/FieldApi.ts:304](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L304) +Defined in: [packages/form-core/src/FieldApi.ts:305](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L305) An optional number to represent how long the `onChangeAsync` should wait before running @@ -151,7 +151,7 @@ If set to a number larger than 0, will debounce the async validation event by th optional onChangeListenTo: DeepKeys[]; ``` -Defined in: [packages/form-core/src/FieldApi.ts:308](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L308) +Defined in: [packages/form-core/src/FieldApi.ts:309](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L309) An optional list of field names that should trigger this field's `onChange` and `onChangeAsync` events when its value changes @@ -163,7 +163,7 @@ An optional list of field names that should trigger this field's `onChange` and optional onMount: TOnMount; ``` -Defined in: [packages/form-core/src/FieldApi.ts:286](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L286) +Defined in: [packages/form-core/src/FieldApi.ts:287](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L287) An optional function, that runs on the mount event of input. @@ -175,7 +175,7 @@ An optional function, that runs on the mount event of input. optional onSubmit: TOnSubmit; ``` -Defined in: [packages/form-core/src/FieldApi.ts:337](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L337) +Defined in: [packages/form-core/src/FieldApi.ts:338](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L338) An optional function, that runs on the submit event of form. @@ -193,7 +193,7 @@ z.string().min(1) optional onSubmitAsync: TOnSubmitAsync; ``` -Defined in: [packages/form-core/src/FieldApi.ts:343](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L343) +Defined in: [packages/form-core/src/FieldApi.ts:344](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L344) An optional property similar to `onSubmit` but async validation. diff --git a/docs/reference/type-aliases/anyfieldapi.md b/docs/reference/type-aliases/anyfieldapi.md index 3f5b3063c..1a44d5328 100644 --- a/docs/reference/type-aliases/anyfieldapi.md +++ b/docs/reference/type-aliases/anyfieldapi.md @@ -11,6 +11,6 @@ title: AnyFieldApi type AnyFieldApi = FieldApi; ``` -Defined in: [packages/form-core/src/FieldApi.ts:811](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L811) +Defined in: [packages/form-core/src/FieldApi.ts:814](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L814) A type representing the Field API with all generics set to `any` for convenience. diff --git a/docs/reference/type-aliases/anyfieldmeta.md b/docs/reference/type-aliases/anyfieldmeta.md index 8b84f14d6..4f33d7694 100644 --- a/docs/reference/type-aliases/anyfieldmeta.md +++ b/docs/reference/type-aliases/anyfieldmeta.md @@ -11,4 +11,4 @@ title: AnyFieldMeta type AnyFieldMeta = FieldMeta; ``` -Defined in: [packages/form-core/src/FieldApi.ts:730](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L730) +Defined in: [packages/form-core/src/FieldApi.ts:733](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L733) diff --git a/docs/reference/type-aliases/anyfieldmetabase.md b/docs/reference/type-aliases/anyfieldmetabase.md index 61ef8ceee..db1e9aba8 100644 --- a/docs/reference/type-aliases/anyfieldmetabase.md +++ b/docs/reference/type-aliases/anyfieldmetabase.md @@ -11,4 +11,4 @@ title: AnyFieldMetaBase type AnyFieldMetaBase = FieldMetaBase; ``` -Defined in: [packages/form-core/src/FieldApi.ts:567](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L567) +Defined in: [packages/form-core/src/FieldApi.ts:570](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L570) diff --git a/docs/reference/type-aliases/anyfieldmetaderived.md b/docs/reference/type-aliases/anyfieldmetaderived.md index 6189f393c..b9a8a3261 100644 --- a/docs/reference/type-aliases/anyfieldmetaderived.md +++ b/docs/reference/type-aliases/anyfieldmetaderived.md @@ -11,4 +11,4 @@ title: AnyFieldMetaDerived type AnyFieldMetaDerived = FieldMetaDerived; ``` -Defined in: [packages/form-core/src/FieldApi.ts:644](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L644) +Defined in: [packages/form-core/src/FieldApi.ts:647](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L647) diff --git a/docs/reference/type-aliases/fieldmeta.md b/docs/reference/type-aliases/fieldmeta.md index c4d16234a..b92195a1b 100644 --- a/docs/reference/type-aliases/fieldmeta.md +++ b/docs/reference/type-aliases/fieldmeta.md @@ -11,7 +11,7 @@ title: FieldMeta type FieldMeta = FieldMetaBase & FieldMetaDerived; ``` -Defined in: [packages/form-core/src/FieldApi.ts:667](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L667) +Defined in: [packages/form-core/src/FieldApi.ts:670](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L670) An object type representing the metadata of a field in a form. diff --git a/docs/reference/type-aliases/fieldmetabase.md b/docs/reference/type-aliases/fieldmetabase.md index 5077778f5..043c1a281 100644 --- a/docs/reference/type-aliases/fieldmetabase.md +++ b/docs/reference/type-aliases/fieldmetabase.md @@ -11,7 +11,7 @@ title: FieldMetaBase type FieldMetaBase = object; ``` -Defined in: [packages/form-core/src/FieldApi.ts:512](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L512) +Defined in: [packages/form-core/src/FieldApi.ts:515](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L515) ## Type Parameters diff --git a/docs/reference/type-aliases/fieldmetaderived.md b/docs/reference/type-aliases/fieldmetaderived.md index 1d2211802..b16b173e3 100644 --- a/docs/reference/type-aliases/fieldmetaderived.md +++ b/docs/reference/type-aliases/fieldmetaderived.md @@ -11,7 +11,7 @@ title: FieldMetaDerived type FieldMetaDerived = object; ``` -Defined in: [packages/form-core/src/FieldApi.ts:587](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L587) +Defined in: [packages/form-core/src/FieldApi.ts:590](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L590) ## Type Parameters diff --git a/docs/reference/type-aliases/fieldstate.md b/docs/reference/type-aliases/fieldstate.md index 5bd0e3c85..be6727599 100644 --- a/docs/reference/type-aliases/fieldstate.md +++ b/docs/reference/type-aliases/fieldstate.md @@ -11,7 +11,7 @@ title: FieldState type FieldState = object; ``` -Defined in: [packages/form-core/src/FieldApi.ts:753](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L753) +Defined in: [packages/form-core/src/FieldApi.ts:756](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L756) An object type representing the state of a field. diff --git a/docs/reference/type-aliases/formvalidationerror.md b/docs/reference/type-aliases/formvalidationerror.md index e8178d450..a1c894218 100644 --- a/docs/reference/type-aliases/formvalidationerror.md +++ b/docs/reference/type-aliases/formvalidationerror.md @@ -13,7 +13,7 @@ type FormValidationError = | GlobalFormValidationError; ``` -Defined in: [packages/form-core/src/types.ts:58](https://github.com/TanStack/form/blob/main/packages/form-core/src/types.ts#L58) +Defined in: [packages/form-core/src/types.ts:63](https://github.com/TanStack/form/blob/main/packages/form-core/src/types.ts#L63) ## Type Parameters diff --git a/docs/reference/type-aliases/unwrapfieldasyncvalidateorfn.md b/docs/reference/type-aliases/unwrapfieldasyncvalidateorfn.md index f775de43d..f93e3ad69 100644 --- a/docs/reference/type-aliases/unwrapfieldasyncvalidateorfn.md +++ b/docs/reference/type-aliases/unwrapfieldasyncvalidateorfn.md @@ -14,7 +14,7 @@ type UnwrapFieldAsyncValidateOrFn = | [TValidateOrFn] extends [FieldValidateAsyncFn] ? Awaited> : [TValidateOrFn] extends [StandardSchemaV1] ? StandardSchemaV1Issue[] : undefined; ``` -Defined in: [packages/form-core/src/FieldApi.ts:203](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L203) +Defined in: [packages/form-core/src/FieldApi.ts:204](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L204) ## Type Parameters diff --git a/docs/reference/type-aliases/unwrapfieldvalidateorfn.md b/docs/reference/type-aliases/unwrapfieldvalidateorfn.md index 5f8b4b354..7852654f5 100644 --- a/docs/reference/type-aliases/unwrapfieldvalidateorfn.md +++ b/docs/reference/type-aliases/unwrapfieldvalidateorfn.md @@ -14,7 +14,7 @@ type UnwrapFieldValidateOrFn = | [TValidateOrFn] extends [FieldValidateFn] ? ReturnType : [TValidateOrFn] extends [StandardSchemaV1] ? StandardSchemaV1Issue[] : undefined; ``` -Defined in: [packages/form-core/src/FieldApi.ts:121](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L121) +Defined in: [packages/form-core/src/FieldApi.ts:122](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L122) ## Type Parameters diff --git a/packages/form-core/src/FieldApi.ts b/packages/form-core/src/FieldApi.ts index 2af502b1b..b3f85f79e 100644 --- a/packages/form-core/src/FieldApi.ts +++ b/packages/form-core/src/FieldApi.ts @@ -20,6 +20,7 @@ import type { FormValidateOrFn, } from './FormApi' import type { + ListenerCause, UpdateMetaOptions, ValidationCause, ValidationError, @@ -349,7 +350,9 @@ export interface FieldListeners< TData extends DeepValue = DeepValue, > { onChange?: FieldListenerFn + onChangeDebounceMs?: number onBlur?: FieldListenerFn + onBlurDebounceMs?: number onMount?: FieldListenerFn onSubmit?: FieldListenerFn } @@ -962,7 +965,10 @@ export class FieldApi< get state() { return this.store.state } - timeoutIds: Record | null> + timeoutIds: { + validations: Record | null> + listeners: Record | null> + } /** * Initializes a new `FieldApi` instance. @@ -992,7 +998,10 @@ export class FieldApi< ) { this.form = opts.form as never this.name = opts.name as never - this.timeoutIds = {} as Record + this.timeoutIds = { + validations: {} as Record, + listeners: {} as Record, + } this.store = new Derived({ deps: [this.form.store], @@ -1175,10 +1184,7 @@ export class FieldApi< setValue = (updater: Updater, options?: UpdateMetaOptions) => { this.form.setFieldValue(this.name, updater as never, options) - this.options.listeners?.onChange?.({ - value: this.state.value, - fieldApi: this, - }) + this.triggerOnChangeListener() this.validate('change') } @@ -1226,10 +1232,7 @@ export class FieldApi< ) => { this.form.pushFieldValue(this.name, value as any, opts) - this.options.listeners?.onChange?.({ - value: this.state.value, - fieldApi: this, - }) + this.triggerOnChangeListener() } /** @@ -1242,10 +1245,7 @@ export class FieldApi< ) => { this.form.insertFieldValue(this.name, index, value as any, opts) - this.options.listeners?.onChange?.({ - value: this.state.value, - fieldApi: this, - }) + this.triggerOnChangeListener() } /** @@ -1258,10 +1258,7 @@ export class FieldApi< ) => { this.form.replaceFieldValue(this.name, index, value as any, opts) - this.options.listeners?.onChange?.({ - value: this.state.value, - fieldApi: this, - }) + this.triggerOnChangeListener() } /** @@ -1270,10 +1267,7 @@ export class FieldApi< removeValue = (index: number, opts?: UpdateMetaOptions) => { this.form.removeFieldValue(this.name, index, opts) - this.options.listeners?.onChange?.({ - value: this.state.value, - fieldApi: this, - }) + this.triggerOnChangeListener() } /** @@ -1282,10 +1276,7 @@ export class FieldApi< swapValues = (aIndex: number, bIndex: number, opts?: UpdateMetaOptions) => { this.form.swapFieldValues(this.name, aIndex, bIndex, opts) - this.options.listeners?.onChange?.({ - value: this.state.value, - fieldApi: this, - }) + this.triggerOnChangeListener() } /** @@ -1294,10 +1285,7 @@ export class FieldApi< moveValue = (aIndex: number, bIndex: number, opts?: UpdateMetaOptions) => { this.form.moveFieldValues(this.name, aIndex, bIndex, opts) - this.options.listeners?.onChange?.({ - value: this.state.value, - fieldApi: this, - }) + this.triggerOnChangeListener() } /** @@ -1502,29 +1490,32 @@ export class FieldApi< let rawError!: ValidationError | undefined try { rawError = await new Promise((rawResolve, rawReject) => { - if (this.timeoutIds[validateObj.cause]) { - clearTimeout(this.timeoutIds[validateObj.cause]!) + if (this.timeoutIds.validations[validateObj.cause]) { + clearTimeout(this.timeoutIds.validations[validateObj.cause]!) } - this.timeoutIds[validateObj.cause] = setTimeout(async () => { - if (controller.signal.aborted) return rawResolve(undefined) - try { - rawResolve( - await this.runValidator({ - validate: validateObj.validate, - value: { - value: field.store.state.value, - fieldApi: field, - signal: controller.signal, - validationSource: 'field', - }, - type: 'validateAsync', - }), - ) - } catch (e) { - rawReject(e) - } - }, validateObj.debounceMs) + this.timeoutIds.validations[validateObj.cause] = setTimeout( + async () => { + if (controller.signal.aborted) return rawResolve(undefined) + try { + rawResolve( + await this.runValidator({ + validate: validateObj.validate, + value: { + value: field.store.state.value, + fieldApi: field, + signal: controller.signal, + validationSource: 'field', + }, + type: 'validateAsync', + }), + ) + } catch (e) { + rawReject(e) + } + }, + validateObj.debounceMs, + ) }) } catch (e: unknown) { rawError = e as ValidationError @@ -1633,10 +1624,7 @@ export class FieldApi< } this.validate('blur') - this.options.listeners?.onBlur?.({ - value: this.state.value, - fieldApi: this, - }) + this.triggerOnBlurListener() } /** @@ -1654,6 +1642,50 @@ export class FieldApi< }) as never, ) } + + private triggerOnBlurListener() { + const debounceMs = this.options.listeners?.onBlurDebounceMs + + if (debounceMs && debounceMs > 0) { + if (this.timeoutIds.listeners.blur) { + clearTimeout(this.timeoutIds.listeners.blur) + } + + this.timeoutIds.listeners.blur = setTimeout(() => { + this.options.listeners?.onBlur?.({ + value: this.state.value, + fieldApi: this, + }) + }, debounceMs) + } else { + this.options.listeners?.onBlur?.({ + value: this.state.value, + fieldApi: this, + }) + } + } + + private triggerOnChangeListener() { + const debounceMs = this.options.listeners?.onChangeDebounceMs + + if (debounceMs && debounceMs > 0) { + if (this.timeoutIds.listeners.change) { + clearTimeout(this.timeoutIds.listeners.change) + } + + this.timeoutIds.listeners.change = setTimeout(() => { + this.options.listeners?.onChange?.({ + value: this.state.value, + fieldApi: this, + }) + }, debounceMs) + } else { + this.options.listeners?.onChange?.({ + value: this.state.value, + fieldApi: this, + }) + } + } } function normalizeError(rawError?: ValidationError) { diff --git a/packages/form-core/src/types.ts b/packages/form-core/src/types.ts index 7dacf8b42..7875a0f92 100644 --- a/packages/form-core/src/types.ts +++ b/packages/form-core/src/types.ts @@ -10,6 +10,11 @@ export type ValidationSource = 'form' | 'field' */ export type ValidationCause = 'change' | 'blur' | 'submit' | 'mount' | 'server' +/** + * @private + */ +export type ListenerCause = 'change' | 'blur' | 'submit' | 'mount' + /** * @private */ diff --git a/packages/form-core/tests/FieldApi.spec.ts b/packages/form-core/tests/FieldApi.spec.ts index 8175718f4..6d8ed17d4 100644 --- a/packages/form-core/tests/FieldApi.spec.ts +++ b/packages/form-core/tests/FieldApi.spec.ts @@ -1890,4 +1890,68 @@ describe('field api', () => { expect(field.getMeta().errors).toStrictEqual([]) expect(form.state.canSubmit).toBe(true) }) + + it('should debounce onChange listener', async () => { + vi.useFakeTimers() + const form = new FormApi({ + defaultValues: { + name: '', + }, + }) + + form.mount() + + const onChangeMock = vi.fn() + const field = new FieldApi({ + form, + name: 'name', + listeners: { + onChange: onChangeMock, + onChangeDebounceMs: 500, + }, + }) + + field.mount() + + field.handleChange('first') + field.handleChange('second') + expect(onChangeMock).not.toHaveBeenCalled() + + await vi.advanceTimersByTimeAsync(500) + expect(onChangeMock).toHaveBeenCalledTimes(1) + expect(onChangeMock).toHaveBeenCalledWith({ + value: 'second', + fieldApi: field, + }) + }) + + it('should debounce onBlur listener', async () => { + vi.useFakeTimers() + const form = new FormApi({ + defaultValues: { + name: '', + }, + }) + + form.mount() + + const onBlurMock = vi.fn() + const field = new FieldApi({ + form, + name: 'name', + listeners: { + onBlur: onBlurMock, + onBlurDebounceMs: 300, + }, + }) + + field.mount() + + field.handleBlur() + field.handleBlur() + expect(onBlurMock).not.toHaveBeenCalled() + + await vi.advanceTimersByTimeAsync(300) + expect(onBlurMock).toHaveBeenCalledTimes(1) + }) })