diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index b8d9d920e..f3b5be6db 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.2.1 + uses: actions/checkout@v4.2.2 - name: Setup Tools uses: tanstack/config/.github/setup@main - name: Fix formatting diff --git a/.nvmrc b/.nvmrc index b8e593f52..1d9b7831b 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20.15.1 +22.12.0 diff --git a/codecov.yml b/codecov.yml index c12fe6e61..7e6c6e200 100755 --- a/codecov.yml +++ b/codecov.yml @@ -2,5 +2,5 @@ coverage: status: project: default: - target: 90% + target: auto threshold: 1% diff --git a/docs/config.json b/docs/config.json index b53c0e8cf..cba1b0137 100644 --- a/docs/config.json +++ b/docs/config.json @@ -101,6 +101,10 @@ "label": "Linked Fields", "to": "framework/react/guides/linked-fields" }, + { + "label": "Listeners", + "to": "framework/react/guides/listeners" + }, { "label": "UI Libraries", "to": "framework/react/guides/ui-libraries" @@ -433,6 +437,21 @@ } ] }, + { + "label": "Community Resources", + "children": [], + "frameworks": [ + { + "label": "react", + "children": [ + { + "label": "Balastrong's Tutorial", + "to": "framework/react/community/balastrong-tutorial" + } + ] + } + ] + }, { "label": "Examples", "children": [], @@ -452,6 +471,10 @@ "label": "TanStack Query Integration", "to": "framework/react/examples/query-integration" }, + { + "label": "Standard Schema", + "to": "framework/react/examples/standard-schema" + }, { "label": "Yup", "to": "framework/react/examples/yup" @@ -472,6 +495,10 @@ "label": "Next Server Actions", "to": "framework/react/examples/next-server-actions" }, + { + "label": "Remix", + "to": "framework/react/examples/remix" + }, { "label": "UI Libraries", "to": "framework/react/examples/ui-libraries" diff --git a/docs/framework/angular/guides/basic-concepts.md b/docs/framework/angular/guides/basic-concepts.md index 5e298359b..1b3da15b8 100644 --- a/docs/framework/angular/guides/basic-concepts.md +++ b/docs/framework/angular/guides/basic-concepts.md @@ -114,14 +114,21 @@ export class AppComponent { } ``` -## Validation Adapters +## Validation with Standard Schema Libraries -In addition to hand-rolled validation options, we also provide adapters like `@tanstack/zod-form-adapter`, `@tanstack/yup-form-adapter`, and `@tanstack/valibot-form-adapter` to enable usage with common schema validation tools like [Zod](https://zod.dev/), [Yup](https://github.com/jquense/yup), and [Valibot](https://valibot.dev/). +In addition to hand-rolled validation options, we also support the [Standard Schema](https://github.com/standard-schema/standard-schema) specification. + +You can define a schema using any of the libraries implementing the specification and pass it to a form or field validator. + +Supported libraries include: + +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) Example: ```angular-ts -import { zodValidator } from '@tanstack/zod-form-adapter' import { z } from 'zod' @Component({ @@ -132,7 +139,6 @@ import { z } from 'zod' + `, +}) + +... + +onCountryChange: FieldListenerFn = ({ + value, + }) => { + console.log(`Country changed to: ${value}, resetting province`) + this.form.setFieldValue('province', '') + } +``` + +More information can be found at [Listeners](./listeners.md) + ## Array Fields Array fields allow you to manage a list of values within a form, such as a list of hobbies. You can create an array field using the `tanstackField` directive. diff --git a/docs/framework/angular/guides/listeners.md b/docs/framework/angular/guides/listeners.md new file mode 100644 index 000000000..80a91b596 --- /dev/null +++ b/docs/framework/angular/guides/listeners.md @@ -0,0 +1,61 @@ +--- +id: listeners +title: Side effects for event triggers +--- + +For situations where you want to "affect" or "react" to triggers, there's the listener API. For example, if you, as the developer, want to reset a form field as a result of another field changing, you would use the listener API. + +Imagine the following user flow: + +- User selects a country from a drop-down. +- User then selects a province from another drop-down. +- User changes the selected country to a different one. + +In this example, when the user changes the country, the selected province needs to be reset as it's no longer valid. With the listener API, we can subscribe to the onChange event and dispatch a reset to the field "province" when the listener is fired. + +Events that can be "listened" to are: + +- onChange +- onBlur +- onMount +- onSubmit + +```angular-ts +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + + `, +}) + +export class AppComponent { + form = injectForm({ + defaultValues: { + country: '', + province: '', + }, + }) + + onCountryChange: FieldListenerFn = ({ + value, + }) => { + console.log(`Country changed to: ${value}, resetting province`) + this.form.setFieldValue('province', '') + } +} +``` diff --git a/docs/framework/angular/guides/validation.md b/docs/framework/angular/guides/validation.md index d5b2f44b2..d9d72352a 100644 --- a/docs/framework/angular/guides/validation.md +++ b/docs/framework/angular/guides/validation.md @@ -382,24 +382,22 @@ This will debounce every async call with a 500ms delay. You can even override th > This will run `onChangeAsync` every 1500ms while `onBlurAsync` will run every 500ms. -## Adapter-Based Validation (Zod, Yup, Valibot) +## Validation through Schema Libraries -While functions provide more flexibility and customization over your validation, they can be a bit verbose. To help solve this, there are libraries like [Valibot](https://valibot.dev/), [Yup](https://github.com/jquense/yup), and [Zod](https://zod.dev/) that provide schema-based validation to make shorthand and type-strict validation substantially easier. +While functions provide more flexibility and customization over your validation, they can be a bit verbose. To help solve this, there are libraries that provide schema-based validation to make shorthand and type-strict validation substantially easier. You can also define a single schema for your entire form and pass it to the form level, errors will be automatically propagated to the fields. -Luckily, we support all of these libraries through official adapters: +### Standard Schema Libraries -```bash -$ npm install @tanstack/zod-form-adapter zod -# or -$ npm install @tanstack/yup-form-adapter yup -# or -$ npm install @tanstack/valibot-form-adapter valibot -``` +TanStack Form natively supports all libraries following the [Standard Schema specification](https://github.com/standard-schema/standard-schema), most notably: +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) -Once done, we can add the adapter to the `validator` property on the form or field: +*Note:* make sure to use the latest version of the schema libraries as older versions might not support Standard Schema yet. + +To use schemas from these libraries you can pass them to the `validators` props as you would do with a custom function: ```angular-ts -import { zodValidator } from '@tanstack/zod-form-adapter' import { z } from 'zod' @Component({ @@ -420,11 +418,9 @@ import { z } from 'zod' `, }) export class AppComponent { - form = injectForm({ - // Either add the validator here or on `Field` - validatorAdapter: zodValidator(), + form = injectForm({ // ... - }) + }) z = z @@ -432,7 +428,8 @@ export class AppComponent { } ``` -These adapters also support async operations using the proper property names: +Async validations on form and field level are supported as well: + ```angular-ts @Component({ @@ -469,37 +466,50 @@ export class AppComponent { } ``` -### Form Level Adapter Validation +### Other Schema Libraries -You can also use the adapter at the form level: +We also support [Yup](https://github.com/jquense/yup) through an official adapter: -```typescript -import { zodValidator } from '@tanstack/zod-form-adapter' -import { z } from 'zod' +```bash +$ npm install @tanstack/yup-form-adapter yup +``` -// ... +Once done, we can add the adapter to the `validator` property on the form or field: -const form = injectForm({ - validatorAdapter: zodValidator(), - validators: { - onChange: z.object({ - age: z.number().gte(13, 'You must be 13 to make an account'), - }), - }, -}) -``` +```angular-ts +import { yupValidator } from '@tanstack/yup-form-adapter' +import * as yup from 'yup' -If you use the adapter at the form level, it will pass the validation to the fields of the same name. +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + + `, +}) +export class AppComponent { + form = injectForm({ + // Either add the validator here or on `Field` + validatorAdapter: yupValidator(), + // ... + }) -This means that: + yup = yup -```html - - - + // ... +} ``` -Will still display the error message from the form-level validation. ## Preventing invalid forms from being submitted diff --git a/docs/framework/angular/reference/classes/tanstackfield.md b/docs/framework/angular/reference/classes/tanstackfield.md index fa74dc32a..3fe19007b 100644 --- a/docs/framework/angular/reference/classes/tanstackfield.md +++ b/docs/framework/angular/reference/classes/tanstackfield.md @@ -46,7 +46,7 @@ api: FieldApi; #### Defined in -[tanstack-field.directive.ts:58](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L58) +[tanstack-field.directive.ts:62](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L62) *** @@ -64,7 +64,7 @@ If `true`, always run async validation, even if there are errors emitted during #### Defined in -[tanstack-field.directive.ts:47](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L47) +[tanstack-field.directive.ts:48](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L48) *** @@ -82,7 +82,7 @@ The default time to debounce async validation if there is not a more specific de #### Defined in -[tanstack-field.directive.ts:46](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L46) +[tanstack-field.directive.ts:47](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L47) *** @@ -100,7 +100,7 @@ An optional object with default metadata for the field. #### Defined in -[tanstack-field.directive.ts:56](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L56) +[tanstack-field.directive.ts:60](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L60) *** @@ -118,7 +118,25 @@ An optional default value for the field. #### Defined in -[tanstack-field.directive.ts:45](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L45) +[tanstack-field.directive.ts:46](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L46) + +*** + +### listeners? + +```ts +optional listeners: NoInfer>; +``` + +A list of listeners which attach to the corresponding events + +#### Implementation of + +`FieldOptions.listeners` + +#### Defined in + +[tanstack-field.directive.ts:57](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L57) *** @@ -136,7 +154,7 @@ The field name. The type will be `DeepKeys` to ensure your name is #### Defined in -[tanstack-field.directive.ts:41](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L41) +[tanstack-field.directive.ts:42](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L42) *** @@ -148,7 +166,7 @@ tanstackField: FormApi; #### Defined in -[tanstack-field.directive.ts:49](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L49) +[tanstack-field.directive.ts:50](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L50) *** @@ -164,7 +182,7 @@ optional unmount: () => void; #### Defined in -[tanstack-field.directive.ts:73](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L73) +[tanstack-field.directive.ts:78](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L78) *** @@ -182,7 +200,7 @@ A validator provided by an extension, like `yupValidator` from `@tanstack/yup-fo #### Defined in -[tanstack-field.directive.ts:48](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L48) +[tanstack-field.directive.ts:49](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L49) *** @@ -200,7 +218,7 @@ A list of validators to pass to the field #### Defined in -[tanstack-field.directive.ts:53](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L53) +[tanstack-field.directive.ts:54](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L54) ## Methods @@ -225,7 +243,7 @@ children are checked. #### Defined in -[tanstack-field.directive.ts:85](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L85) +[tanstack-field.directive.ts:90](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L90) *** @@ -248,7 +266,7 @@ before a directive, pipe, or service instance is destroyed. #### Defined in -[tanstack-field.directive.ts:81](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L81) +[tanstack-field.directive.ts:86](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L86) *** @@ -274,4 +292,4 @@ It is invoked only once when the directive is instantiated. #### Defined in -[tanstack-field.directive.ts:75](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L75) +[tanstack-field.directive.ts:80](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L80) diff --git a/docs/framework/angular/reference/functions/injectform.md b/docs/framework/angular/reference/functions/injectform.md index 3ead8f1ca..235cfa030 100644 --- a/docs/framework/angular/reference/functions/injectform.md +++ b/docs/framework/angular/reference/functions/injectform.md @@ -17,7 +17,9 @@ function injectForm(opts?): FormApi +### opts? + +`FormOptions`\<`TFormData`, `TFormValidator`\> ## Returns diff --git a/docs/framework/angular/reference/functions/injectstore.md b/docs/framework/angular/reference/functions/injectstore.md index 1fee88e76..e5a765b72 100644 --- a/docs/framework/angular/reference/functions/injectstore.md +++ b/docs/framework/angular/reference/functions/injectstore.md @@ -19,9 +19,13 @@ function injectStore(form, selector?): Sig ## Parameters -• **form**: `FormApi`\<`TFormData`, `TFormValidator`\> +### form -• **selector?** +`FormApi`\<`TFormData`, `TFormValidator`\> + +### selector? + +(`state`) => `TSelected` ## Returns diff --git a/docs/framework/lit/reference/classes/tanstackformcontroller.md b/docs/framework/lit/reference/classes/tanstackformcontroller.md index 95e7e5ad1..b918a06a6 100644 --- a/docs/framework/lit/reference/classes/tanstackformcontroller.md +++ b/docs/framework/lit/reference/classes/tanstackformcontroller.md @@ -25,9 +25,13 @@ new TanStackFormController(host, config?): TanStack #### Parameters -• **host**: `ReactiveControllerHost` +##### host -• **config?**: `FormOptions`\<`TParentData`, `TFormValidator`\> +`ReactiveControllerHost` + +##### config? + +`FormOptions`\<`TParentData`, `TFormValidator`\> #### Returns @@ -67,9 +71,13 @@ field(fieldConfig, render): object #### Parameters -• **fieldConfig**: `FieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +##### fieldConfig + +`FieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> + +##### render -• **render**: `renderCallback`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +`renderCallback`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> #### Returns @@ -81,19 +89,19 @@ field(fieldConfig, render): object values: object; ``` -##### values.form +###### values.form ```ts form: FormApi; ``` -##### values.options +###### values.options ```ts options: FieldOptions; ``` -##### values.render +###### values.render ```ts render: renderCallback; diff --git a/docs/framework/react/community/balastrong-tutorial.md b/docs/framework/react/community/balastrong-tutorial.md new file mode 100644 index 000000000..f6fba45df --- /dev/null +++ b/docs/framework/react/community/balastrong-tutorial.md @@ -0,0 +1,33 @@ +--- +id: balastrong-tutorial +title: Balastrong's Tutorial +--- + +TanStack Form maintainer [Balastrong](https://bsky.app/profile/leonardomontini.dev) has created a series of video tutorials showcasing the most relevant features of the library. You'll find step by step guides that give you some extra insights into what you can build with TanStack Form, plus some nice tips and tricks. + +[Watch the full playlist](https://www.youtube.com/playlist?list=PLOQjd5dsGSxInTKUWTxyqSKwZCjDIUs0Y) + + +## 1. [Setup and validation](https://youtu.be/Pf1qn35bgjs) + +The first steps into TanStack Form learning all the basics, from setting up the library to creating a simple form with text fields and validation (sync, debounced and async). [Watch video (8:16)](https://youtu.be/Pf1qn35bgjs) + +## 2. [Advanced validation](https://youtu.be/Pys2ExswZT0) + +An example of data being validated through a backend API while ensuring a smooth user experience by controlling loading state, error messages and linked fields. [Watch video (8:05)](https://youtu.be/Pys2ExswZT0) + +## 3. [Array fields](https://youtu.be/0IPPHdjvrzk) + +How to handle array fields with primitives (strings, numbers) and objects (nested fields), with validation and reordering. [Watch video (6:53)](https://youtu.be/0IPPHdjvrzk) + +## 4. [Reactivity](https://youtu.be/UXRZvNCnE-s) + +Learn why form values may not update in real time, why this behavior is intentional, and how to trigger UI updates efficiently. [Watch video (4:26)](https://youtu.be/UXRZvNCnE-s) + +## 5. [Form validation with schema libraries](https://youtu.be/HSboMHfPuZA) + +Use schema libraries like zod, yup or valibot to define your schema with validation rules. Pass it to TanStack Form through an adapter to validate all fields at once. [Watch video (6:29)](https://youtu.be/HSboMHfPuZA) + +## 6. [Side effects and listeners](https://youtu.be/A-w2IG7DAso) + +Similarly to field validators, you can attach events to field listeners and react to them, for example to reset a field when another one it depends on has changed. [Watch video (5:50)](https://youtu.be/A-w2IG7DAso) \ No newline at end of file diff --git a/docs/framework/react/guides/basic-concepts.md b/docs/framework/react/guides/basic-concepts.md index 51045f253..a8528eb4f 100644 --- a/docs/framework/react/guides/basic-concepts.md +++ b/docs/framework/react/guides/basic-concepts.md @@ -144,44 +144,55 @@ Example: /> ``` -## Validation Adapters +## Validation with Standard Schema Libraries -In addition to hand-rolled validation options, we also provide adapters like `@tanstack/zod-form-adapter`, `@tanstack/yup-form-adapter`, and `@tanstack/valibot-form-adapter` to enable usage with common schema validation tools like [Zod](https://zod.dev/), [Yup](https://github.com/jquense/yup), and [Valibot](https://valibot.dev/). +In addition to hand-rolled validation options, we also support the [Standard Schema](https://github.com/standard-schema/standard-schema) specification. -Example: +You can define a schema using any of the libraries implementing the specification and pass it to a form or field validator. + +Supported libraries include: + +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) ```tsx -import { zodValidator } from '@tanstack/zod-form-adapter' import { z } from 'zod' -// ... - { - await new Promise((resolve) => setTimeout(resolve, 1000)) - return !value.includes('error') - }, - { - message: "No 'error' allowed in first name", - }, - ), - }} -/> +const userSchema = z.object({ + age: z.number().gte(13, 'You must be 13 to make an account'), +}) + +function App() { + const form = useForm({ + defaultValues: { + age: 0, + }, + validators: { + onChange: userSchema, + }, + }) + return ( +
+ { + return <>{/* ... */} + }} + /> +
+ ) +} ``` ## Reactivity -`@tanstack/react-form` offers various ways to subscribe to form and field state changes, most notably the `form.useStore` hook and the `form.Subscribe` component. These methods allow you to optimize your form's rendering performance by only updating components when necessary. +`@tanstack/react-form` offers various ways to subscribe to form and field state changes, most notably the `useStore(form.store)` hook and the `form.Subscribe` component. These methods allow you to optimize your form's rendering performance by only updating components when necessary. Example: ```tsx -const firstName = form.useStore((state) => state.values.firstName) +const firstName = useStore(form.store, (state) => state.values.firstName) //... [state.canSubmit, state.isSubmitting]} @@ -193,7 +204,27 @@ const firstName = form.useStore((state) => state.values.firstName) /> ``` -Note: The usage of the `form.useField` hook to achieve reactivity is discouraged since it is designed to be used thoughtfully within the `form.Field` component. You might want to use `form.useStore` instead. +Note: The usage of the `useField` hook to achieve reactivity is discouraged since it is designed to be used thoughtfully within the `form.Field` component. You might want to use `useStore(form.store)` instead. + +## Listeners + +`@tanstack/react-form` allows you to react to specific triggers and "listen" to them to dispatch side effects. + +Example: + +```tsx + { + console.log(`Country changed to: ${value}, resetting province`) + form.setFieldValue('province', '') + } + }} +/> +``` + +More information can be found at [Listeners](./listeners.md) ## Array Fields diff --git a/docs/framework/react/guides/listeners.md b/docs/framework/react/guides/listeners.md new file mode 100644 index 000000000..21357455b --- /dev/null +++ b/docs/framework/react/guides/listeners.md @@ -0,0 +1,69 @@ +--- +id: listeners +title: Side effects for event triggers +--- + +For situations where you want to "affect" or "react" to triggers, there's the listener API. For example, if you, as the developer, want to reset a form field as a result of another field changing, you would use the listener API. + +Imagine the following user flow: + +- User selects a country from a drop-down. +- User then selects a province from another drop-down. +- User changes the selected country to a different one. + +In this example, when the user changes the country, the selected province needs to be reset as it's no longer valid. With the listener API, we can subscribe to the onChange event and dispatch a reset to the field "province" when the listener is fired. + +Events that can be "listened" to are: + +- onChange +- onBlur +- onMount +- onSubmit + +```tsx +function App() { + const form = useForm({ + defaultValues: { + country: '', + province: '', + }, + // ... + }) + + return ( +
+ { + console.log(`Country changed to: ${value}, resetting province`); + form.setFieldValue("province", ""); + }, + }} + > + {(field) => ( + + )} + + + + {(field) => ( + + )} + +
+ ) +} +``` diff --git a/docs/framework/react/guides/ssr.md b/docs/framework/react/guides/ssr.md index 76a54cadb..f584a792c 100644 --- a/docs/framework/react/guides/ssr.md +++ b/docs/framework/react/guides/ssr.md @@ -9,8 +9,8 @@ Today we support the following meta-frameworks: - [TanStack Start](https://tanstack.com/start/) - [Next.js](https://nextjs.org/) +- [Remix](https://remix.run) -_We need help adding Remix support! [Come help us research and implement it here.](https://github.com/TanStack/form/issues/759)_ ## Using TanStack Form in TanStack Start @@ -20,7 +20,7 @@ This section focuses on integrating TanStack Form with TanStack Start. - Start a new `TanStack Start` project, following the steps in the [TanStack Start Quickstart Guide](https://tanstack.com/router/latest/docs/framework/react/guide/tanstack-start) - Install `@tanstack/react-form` -- Install any [form validator](/form/latest/docs/framework/react/guides/validation#adapter-based-validation-zod-yup-valibot) of your choice. [Optional] +- Install any [form validator](/form/latest/docs/framework/react/guides/validation#validation-through-schema-libraries) of your choice. [Optional] ### Start integration @@ -114,7 +114,7 @@ function Home() { transform: useTransform((baseForm) => mergeForm(baseForm, state), [state]), }) - const formErrors = form.useStore((formState) => formState.errors) + const formErrors = useStore(form.store, (formState) => formState.errors) return (
@@ -169,7 +169,7 @@ This section focuses on integrating TanStack Form with `Next.js`, particularly u - Start a new `Next.js` project, following the steps in the [Next.js Documentation](https://nextjs.org/docs/getting-started/installation). Ensure you select `yes` for `Would you like to use App Router?` during the setup to access all new features provided by Next.js. - Install `@tanstack/react-form` -- Install any [form validator](/form/latest/docs/framework/react/guides/validation#adapter-based-validation-zod-yup-valibot) of your choice. [Optional] +- Install any [form validator](/form/latest/docs/framework/react/guides/validation#validation-through-schema-libraries) of your choice. [Optional] ## App Router integration @@ -249,7 +249,7 @@ export const ClientComp = () => { transform: useTransform((baseForm) => mergeForm(baseForm, state!), [state]), }) - const formErrors = form.useStore((formState) => formState.errors) + const formErrors = useStore(form.store, (formState) => formState.errors) return ( form.handleSubmit()}> @@ -306,3 +306,154 @@ Here, we're using [React's `useActionState` hook](https://unicorn-utterances.com > > > [This is a limitation of Next.js](https://github.com/phryneas/rehackt). Other meta-frameworks will likely not have this same problem. + +## Using TanStack Form in Remix + +> Before reading this section, it's suggested you understand how Remix actions work. [Check out Remix's docs for more information](https://remix.run/docs/en/main/discussion/data-flow#route-action) + +### Remix Prerequisites + +- Start a new `Remix` project, following the steps in the [Remix Documentation](https://remix.run/docs/en/main/start/quickstart). +- Install `@tanstack/react-form` +- Install any [form validator](/form/latest/docs/framework/react/guides/validation#validation-through-schema-libraries) of your choice. [Optional] + +## Remix integration + +Let's start by creating a `formOption` that we'll use to share the form's shape across the client and server. + + +```typescript +// routes/_index/route.tsx +import { formOptions } from '@tanstack/react-form/remix' + +// You can pass other form options here, like `validatorAdapter` +export const formOpts = formOptions({ + defaultValues: { + firstName: '', + age: 0, + }, +}) +``` + +Next, we can create [an action](https://remix.run/docs/en/main/discussion/data-flow#route-action) that will handle the form submission on the server. + +```tsx +// routes/_index/route.tsx + +import { + ServerValidateError, + createServerValidate, + formOptions +} from '@tanstack/react-form/remix' + +import type { ActionFunctionArgs } from '@remix-run/node' + +// export const formOpts = formOptions({ + +// Create the server action that will infer the types of the form from `formOpts` +const serverValidate = createServerValidate({ + ...formOpts, + onServerValidate: ({ value }) => { + if (value.age < 12) { + return 'Server validation: You must be at least 12 to sign up' + } + }, +}) + +export async function action({request}: ActionFunctionArgs) { + const formData = await request.formData() + try { + await serverValidate(formData) + } catch (e) { + if (e instanceof ServerValidateError) { + return e.formState + } + + // Some other error occurred while validating your form + throw e + } + + // Your form has successfully validated! + +} +``` + +Finally, the `action` will be called when the form submits. + +```tsx +// routes/_index/route.tsx +import { Form, useActionData } from '@remix-run/react' + +import { mergeForm, useForm, useTransform } from '@tanstack/react-form' +import { + ServerValidateError, + createServerValidate, + formOptions, + initialFormState, +} from '@tanstack/react-form/remix' + +import type { ActionFunctionArgs } from '@remix-run/node' + +// export const formOpts = formOptions({ + +// const serverValidate = createServerValidate({ + +// export async function action({request}: ActionFunctionArgs) { + +export default function Index() { + const actionData = useActionData() + + const form = useForm({ + ...formOpts, + transform: useTransform( + (baseForm) => mergeForm(baseForm, actionData ?? initialFormState), + [actionData], + ), + }) + + const formErrors = useStore(form.store, (formState) => formState.errors) + + return ( + form.handleSubmit()}> + {formErrors.map((error) => ( +

{error}

+ ))} + + + value < 8 ? 'Client validation: You must be at least 8' : undefined, + }} + > + {(field) => { + return ( +
+ field.handleChange(e.target.valueAsNumber)} + /> + {field.state.meta.errors.map((error) => ( +

{error}

+ ))} +
+ ) + }} +
+ [formState.canSubmit, formState.isSubmitting]} + > + {([canSubmit, isSubmitting]) => ( + + )} + + + ) +} +``` + +Here, we're using [Remix's `useActionData` hook](https://remix.run/docs/en/main/hooks/use-action-data) and TanStack Form's `useTransform` hook to merge state returned from the server action with the form state. diff --git a/docs/framework/react/guides/validation.md b/docs/framework/react/guides/validation.md index 21a6d4424..e8a9ff26f 100644 --- a/docs/framework/react/guides/validation.md +++ b/docs/framework/react/guides/validation.md @@ -178,7 +178,7 @@ export default function App() { // Subscribe to the form's error map so that updates to it will render // alternately, you can use `form.Subscribe` - const formErrorMap = form.useStore((state) => state.errorMap) + const formErrorMap = useStore(form.store, (state) => state.errorMap) return (
@@ -413,47 +413,49 @@ This will debounce every async call with a 500ms delay. You can even override th > This will run `onChangeAsync` every 1500ms while `onBlurAsync` will run every 500ms. -## Adapter-Based Validation (Zod, Yup, Valibot) +## Validation through Schema Libraries -While functions provide more flexibility and customization over your validation, they can be a bit verbose. To help solve this, there are libraries like [Valibot](https://valibot.dev/), [Yup](https://github.com/jquense/yup), and [Zod](https://zod.dev/) that provide schema-based validation to make shorthand and type-strict validation substantially easier. +While functions provide more flexibility and customization over your validation, they can be a bit verbose. To help solve this, there are libraries that provide schema-based validation to make shorthand and type-strict validation substantially easier. You can also define a single schema for your entire form and pass it to the form level, errors will be automatically propagated to the fields. -Luckily, we support all of these libraries through official adapters: +### Standard Schema Libraries -```bash -$ npm install @tanstack/zod-form-adapter zod -# or -$ npm install @tanstack/yup-form-adapter yup -# or -$ npm install @tanstack/valibot-form-adapter valibot -``` +TanStack Form natively supports all libraries following the [Standard Schema specification](https://github.com/standard-schema/standard-schema), most notably: +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) -Once done, we can add the adapter to the `validator` property on the form or field: +*Note:* make sure to use the latest version of the schema libraries as older versions might not support Standard Schema yet. -```tsx -import { zodValidator } from '@tanstack/zod-form-adapter' -import { z } from 'zod' - -// ... +To use schemas from these libraries you can pass them to the `validators` props as you would do with a custom function: -const form = useForm({ - // Either add the validator here or on `Field` - validatorAdapter: zodValidator(), - // ... +```tsx +const userSchema = z.object({ + age: z.number().gte(13, 'You must be 13 to make an account'), }) - { - return <>{/* ... */} - }} -/> +function App() { + const form = useForm({ + defaultValues: { + age: 0, + }, + validators: { + onChange: userSchema, + }, + }) + return ( +
+ { + return <>{/* ... */} + }} + /> +
+ ) +} ``` -These adapters also support async operations using the proper property names: +Async validations on form and field level are supported as well: ```tsx ``` -### Form Level Adapter Validation +### Other Schema Libraries + +We also support [Yup](https://github.com/jquense/yup) through an official adapter: -You can also use the adapter at the form level: +```bash +$ npm install @tanstack/yup-form-adapter yup +``` + +Once done, we can add the adapter to the `validator` property on the form or field: ```tsx -import { zodValidator } from '@tanstack/zod-form-adapter' -import { z } from 'zod' +import { yupValidator } from '@tanstack/yup-form-adapter' +import * as yup from 'yup' // ... -const formSchema = z.object({ - age: z.number().gte(13, 'You must be 13 to make an account'), -}) - const form = useForm({ - validatorAdapter: zodValidator(), - validators: { - onChange: formSchema - }, + // Either add the validator here or on `Field` + validatorAdapter: yupValidator(), + // ... }) -``` - -If you use the adapter at the form level, it will pass the validation to the fields of the same name. - -This means that: - -```tsx { return <>{/* ... */} }} /> ``` -Will still display the error message from the form-level validation. - ## Preventing invalid forms from being submitted The `onChange`, `onBlur` etc... callbacks are also run when the form is submitted and the submission is blocked if the form is invalid. diff --git a/docs/framework/react/reference/functions/field.md b/docs/framework/react/reference/functions/field.md index fddb0a969..c1ac1504d 100644 --- a/docs/framework/react/reference/functions/field.md +++ b/docs/framework/react/reference/functions/field.md @@ -27,7 +27,9 @@ The `Field` component uses the `useField` hook internally to manage the field in ## Parameters -• **\_\_namedParameters**: `FieldComponentProps`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +### \_\_namedParameters + +`FieldComponentProps`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> ## Returns @@ -35,4 +37,4 @@ The `Field` component uses the `useField` hook internally to manage the field in ## Defined in -[useField.tsx:164](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L164) +[packages/react-form/src/useField.tsx:164](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L164) diff --git a/docs/framework/react/reference/functions/usefield.md b/docs/framework/react/reference/functions/usefield.md index 0d341f855..779a1954e 100644 --- a/docs/framework/react/reference/functions/usefield.md +++ b/docs/framework/react/reference/functions/usefield.md @@ -25,7 +25,9 @@ A hook for managing a field in a form. ## Parameters -• **opts**: `UseFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +### opts + +`UseFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> An object with field options. @@ -37,4 +39,4 @@ The `FieldApi` instance for the specified field. ## Defined in -[useField.tsx:50](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L50) +[packages/react-form/src/useField.tsx:50](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L50) diff --git a/docs/framework/react/reference/functions/useform.md b/docs/framework/react/reference/functions/useform.md index f0a52bf6e..6f877b2e9 100644 --- a/docs/framework/react/reference/functions/useform.md +++ b/docs/framework/react/reference/functions/useform.md @@ -6,7 +6,7 @@ title: useForm # Function: useForm() ```ts -function useForm(opts?): FormApi & ReactFormApi +function useForm(opts?): ReactFormExtendedApi ``` A custom React Hook that returns an extended instance of the `FormApi` class. @@ -21,12 +21,14 @@ This API encapsulates all the necessary functionalities related to the form. It ## Parameters -• **opts?**: `FormOptions`\<`TFormData`, `TFormValidator`\> +### opts? + +`FormOptions`\<`TFormData`, `TFormValidator`\> ## Returns -`FormApi`\<`TFormData`, `TFormValidator`\> & [`ReactFormApi`](../interfaces/reactformapi.md)\<`TFormData`, `TFormValidator`\> +[`ReactFormExtendedApi`](../type-aliases/reactformextendedapi.md)\<`TFormData`, `TFormValidator`\> ## Defined in -[useForm.tsx:57](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L57) +[packages/react-form/src/useForm.tsx:57](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L57) diff --git a/docs/framework/react/reference/functions/usestore.md b/docs/framework/react/reference/functions/usestore.md new file mode 100644 index 000000000..45ed3f214 --- /dev/null +++ b/docs/framework/react/reference/functions/usestore.md @@ -0,0 +1,66 @@ +--- +id: useStore +title: useStore +--- + +# Function: useStore() + +## Call Signature + +```ts +function useStore(store, selector?): TSelected +``` + +### Type Parameters + +• **TState** + +• **TSelected** = `NoInfer`\<`TState`\> + +### Parameters + +#### store + +`Store`\<`TState`, `any`\> + +#### selector? + +(`state`) => `TSelected` + +### Returns + +`TSelected` + +### Defined in + +node\_modules/.pnpm/@tanstack+react-store@0.7.0\_react-dom@18.3.1\_react@18.3.1\_\_react@18.3.1/node\_modules/@tanstack/react-store/dist/esm/index.d.ts:7 + +## Call Signature + +```ts +function useStore(store, selector?): TSelected +``` + +### Type Parameters + +• **TState** + +• **TSelected** = `NoInfer`\<`TState`\> + +### Parameters + +#### store + +`Derived`\<`TState`, `any`\> + +#### selector? + +(`state`) => `TSelected` + +### Returns + +`TSelected` + +### Defined in + +node\_modules/.pnpm/@tanstack+react-store@0.7.0\_react-dom@18.3.1\_react@18.3.1\_\_react@18.3.1/node\_modules/@tanstack/react-store/dist/esm/index.d.ts:8 diff --git a/docs/framework/react/reference/functions/usetransform.md b/docs/framework/react/reference/functions/usetransform.md index 647b76fac..bc4ffb2cb 100644 --- a/docs/framework/react/reference/functions/usetransform.md +++ b/docs/framework/react/reference/functions/usetransform.md @@ -17,9 +17,13 @@ function useTransform(fn, deps): FormTransform `FormApi`\<`TFormData`, `TFormValidator`\> + +### deps + +`unknown`[] ## Returns @@ -27,4 +31,4 @@ function useTransform(fn, deps): FormTransform `ReactNode` +###### children -• **props.selector?** +`ReactNode` \| (`state`) => `ReactNode` -TypeScript versions <=5.0.4 have a bug that prevents -the type of the `TSelected` generic from being inferred -from the return type of this method. +###### selector -In these versions, `TSelected` will fall back to the default -type (or `unknown` if that's not defined). - -**See** - - - [This discussion on GitHub for the details](https://github.com/TanStack/form/pull/606/files#r1506715714) - - [The bug report in `microsoft/TypeScript`](https://github.com/microsoft/TypeScript/issues/52786) +(`state`) => `TSelected` #### Returns @@ -67,44 +59,4 @@ type (or `unknown` if that's not defined). #### Defined in -[useForm.tsx:35](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L35) - -*** - -### useField - -```ts -useField: UseField; -``` - -A custom React hook that provides functionalities related to individual form fields. It gives you access to field values, errors, and allows you to set or update field values. - -#### Defined in - -[useForm.tsx:25](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L25) - -*** - -### useStore() - -```ts -useStore: (selector?) => TSelected; -``` - -A `useStore` hook that connects to the internal store of the form. It can be used to access the form's current state or any other related state information. You can optionally pass in a selector function to cherry-pick specific parts of the state - -#### Type Parameters - -• **TSelected** = `FormState`\<`TFormData`\> - -#### Parameters - -• **selector?** - -#### Returns - -`TSelected` - -#### Defined in - -[useForm.tsx:29](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L29) +[packages/react-form/src/useForm.tsx:25](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L25) diff --git a/docs/framework/react/reference/type-aliases/fieldcomponent.md b/docs/framework/react/reference/type-aliases/fieldcomponent.md index 079e22883..7e72e1ea8 100644 --- a/docs/framework/react/reference/type-aliases/fieldcomponent.md +++ b/docs/framework/react/reference/type-aliases/fieldcomponent.md @@ -9,7 +9,7 @@ title: FieldComponent type FieldComponent: ({ children, ...fieldOptions -}) => NodeType; +}) => ReactNode; ``` A type alias representing a field component for a specific form data type. @@ -30,15 +30,17 @@ A type alias representing a field component for a specific form data type. ## Parameters -• **\{ +### \{ children, ...fieldOptions -\}**: `Omit`\<`FieldComponentProps`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> +\} + +`Omit`\<`FieldComponentProps`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> ## Returns -`NodeType` +`ReactNode` ## Defined in -[useField.tsx:134](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L134) +[packages/react-form/src/useField.tsx:134](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L134) diff --git a/docs/framework/react/reference/type-aliases/reactformextendedapi.md b/docs/framework/react/reference/type-aliases/reactformextendedapi.md new file mode 100644 index 000000000..15527cba0 --- /dev/null +++ b/docs/framework/react/reference/type-aliases/reactformextendedapi.md @@ -0,0 +1,22 @@ +--- +id: ReactFormExtendedApi +title: ReactFormExtendedApi +--- + +# Type Alias: ReactFormExtendedApi\ + +```ts +type ReactFormExtendedApi: FormApi & ReactFormApi; +``` + +An extended version of the `FormApi` class that includes React-specific functionalities from `ReactFormApi` + +## Type Parameters + +• **TFormData** + +• **TFormValidator** *extends* `Validator`\<`TFormData`, `unknown`\> \| `undefined` = `undefined` + +## Defined in + +[packages/react-form/src/useForm.tsx:34](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L34) diff --git a/docs/framework/react/reference/type-aliases/usefield.md b/docs/framework/react/reference/type-aliases/usefield.md index 831214e47..27f17d13f 100644 --- a/docs/framework/react/reference/type-aliases/usefield.md +++ b/docs/framework/react/reference/type-aliases/usefield.md @@ -29,7 +29,9 @@ A function that takes an optional object with a `name` property and field option ## Parameters -• **opts**: `Omit`\<`UseFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> +### opts + +`Omit`\<`UseFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> ## Returns @@ -37,4 +39,4 @@ A function that takes an optional object with a `name` property and field option ## Defined in -[useField.tsx:26](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L26) +[packages/react-form/src/useField.tsx:26](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L26) diff --git a/docs/framework/solid/guides/basic-concepts.md b/docs/framework/solid/guides/basic-concepts.md index eb3cf2a13..ff9cbce5a 100644 --- a/docs/framework/solid/guides/basic-concepts.md +++ b/docs/framework/solid/guides/basic-concepts.md @@ -139,20 +139,24 @@ Example: /> ``` -## Validation Adapters +## Validation with Standard Schema Libraries -In addition to hand-rolled validation options, we also provide adapters like `@tanstack/zod-form-adapter`, `@tanstack/yup-form-adapter`, and `@tanstack/valibot-form-adapter` to enable usage with common schema validation tools like [Zod](https://zod.dev/), [Yup](https://github.com/jquense/yup), and [Valibot](https://valibot.dev/). +In addition to hand-rolled validation options, we also support the [Standard Schema](https://github.com/standard-schema/standard-schema) specification. -Example: +You can define a schema using any of the libraries implementing the specification and pass it to a form or field validator. + +Supported libraries include: + +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) ```tsx -import { zodValidator } from '@tanstack/zod-form-adapter' import { z } from 'zod' // ... This will run `onChangeAsync` every 1500ms while `onBlurAsync` will run every 500ms. -## Adapter-Based Validation (Zod, Yup, Valibot) +## Validation through Schema Libraries -While functions provide more flexibility and customization over your validation, they can be a bit verbose. To help solve this, there are libraries like [Valibot](https://valibot.dev/), [Yup](https://github.com/jquense/yup), and [Zod](https://zod.dev/) that provide schema-based validation to make shorthand and type-strict validation substantially easier. +While functions provide more flexibility and customization over your validation, they can be a bit verbose. To help solve this, there are libraries that provide schema-based validation to make shorthand and type-strict validation substantially easier. You can also define a single schema for your entire form and pass it to the form level, errors will be automatically propagated to the fields. -Luckily, we support all of these libraries through official adapters: +### Standard Schema Libraries -```bash -$ npm install @tanstack/zod-form-adapter zod -# or -$ npm install @tanstack/yup-form-adapter yup -# or -$ npm install @tanstack/valibot-form-adapter valibot -``` +TanStack Form natively supports all libraries following the [Standard Schema specification](https://github.com/standard-schema/standard-schema), most notably: +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) -Once done, we can add the adapter to the `validator` property on the form or field: +*Note:* make sure to use the latest version of the schema libraries as older versions might not support Standard Schema yet. + +To use schemas from these libraries you can pass them to the `validators` props as you would do with a custom function: ```tsx -import { zodValidator } from '@tanstack/zod-form-adapter' import { z } from 'zod' // ... const form = createForm(() => ({ - // Either add the validator here or on `Field` - validatorAdapter: zodValidator(), // ... })); ({ /> ``` -These adapters also support async operations using the proper property names: +Async validations on form and field level are supported as well: ```tsx ``` -### Form Level Adapter Validation +### Other Schema Libraries +We also support [Yup](https://github.com/jquense/yup) through an official adapter: + +```bash +$ npm install @tanstack/yup-form-adapter yup +``` + +Once done, we can add the adapter to the `validator` property on the form or field: -You can also use the adapter at the form level: ```tsx -import { zodValidator } from '@tanstack/zod-form-adapter' -import { z } from 'zod' +import { yupValidator } from '@tanstack/yup-form-adapter' +import * as yup from 'yup' // ... const form = createForm(() => ({ - validatorAdapter: zodValidator(), - validators: { - onChange: z.object({ - age: z.number().gte(13, 'You must be 13 to make an account'), - }), - }, -})) -``` - -If you use the adapter at the form level, it will pass the validation to the fields of the same name. - -This means that: - -```tsx + // Either add the validator here or on `Field` + validatorAdapter: yupValidator(), + // ... +})); { return <>{/* ... */} }} /> ``` -Will still display the error message from the form-level validation. - - ## Preventing invalid forms from being submitted The `onChange`, `onBlur` etc... callbacks are also run when the form is submitted and the submission is blocked if the form is invalid. diff --git a/docs/framework/solid/reference/functions/createfield.md b/docs/framework/solid/reference/functions/createfield.md index d4cbbcf3b..b03c59dc1 100644 --- a/docs/framework/solid/reference/functions/createfield.md +++ b/docs/framework/solid/reference/functions/createfield.md @@ -23,7 +23,9 @@ function createField ## Parameters -• **opts** +### opts + +() => `CreateFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> ## Returns @@ -35,4 +37,4 @@ function createField ## Defined in -[createField.tsx:87](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L87) +[packages/solid-form/src/createField.tsx:87](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L87) diff --git a/docs/framework/solid/reference/functions/createform.md b/docs/framework/solid/reference/functions/createform.md index ee2fd0d57..1de39fc10 100644 --- a/docs/framework/solid/reference/functions/createform.md +++ b/docs/framework/solid/reference/functions/createform.md @@ -17,7 +17,9 @@ function createForm(opts?): FormApi `FormOptions`\<`TParentData`, `TFormValidator`\> ## Returns @@ -25,4 +27,4 @@ function createForm(opts?): FormApi(props ## Parameters -• **props**: `object` & `FieldApiOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> & `object` +### props + +`object` & `FieldApiOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> & `object` ## Returns @@ -31,4 +33,4 @@ function Field(props ## Defined in -[createField.tsx:185](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L185) +[packages/solid-form/src/createField.tsx:196](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L196) diff --git a/docs/framework/solid/reference/functions/usestore.md b/docs/framework/solid/reference/functions/usestore.md new file mode 100644 index 000000000..69e1e4e37 --- /dev/null +++ b/docs/framework/solid/reference/functions/usestore.md @@ -0,0 +1,66 @@ +--- +id: useStore +title: useStore +--- + +# Function: useStore() + +## Call Signature + +```ts +function useStore(store, selector?): Accessor +``` + +### Type Parameters + +• **TState** + +• **TSelected** = `NoInfer`\<`TState`\> + +### Parameters + +#### store + +`Store`\<`TState`, `any`\> + +#### selector? + +(`state`) => `TSelected` + +### Returns + +`Accessor`\<`TSelected`\> + +### Defined in + +node\_modules/.pnpm/@tanstack+solid-store@0.7.0\_solid-js@1.9.3/node\_modules/@tanstack/solid-store/dist/esm/index.d.ts:8 + +## Call Signature + +```ts +function useStore(store, selector?): Accessor +``` + +### Type Parameters + +• **TState** + +• **TSelected** = `NoInfer`\<`TState`\> + +### Parameters + +#### store + +`Derived`\<`TState`, `any`\> + +#### selector? + +(`state`) => `TSelected` + +### Returns + +`Accessor`\<`TSelected`\> + +### Defined in + +node\_modules/.pnpm/@tanstack+solid-store@0.7.0\_solid-js@1.9.3/node\_modules/@tanstack/solid-store/dist/esm/index.d.ts:9 diff --git a/docs/framework/solid/reference/index.md b/docs/framework/solid/reference/index.md index eafeb8042..704a66cb7 100644 --- a/docs/framework/solid/reference/index.md +++ b/docs/framework/solid/reference/index.md @@ -19,3 +19,4 @@ title: "@tanstack/solid-form" - [createField](functions/createfield.md) - [createForm](functions/createform.md) - [Field](functions/field.md) +- [useStore](functions/usestore.md) diff --git a/docs/framework/solid/reference/interfaces/solidformapi.md b/docs/framework/solid/reference/interfaces/solidformapi.md index ab0a76bdd..048fa225a 100644 --- a/docs/framework/solid/reference/interfaces/solidformapi.md +++ b/docs/framework/solid/reference/interfaces/solidformapi.md @@ -21,7 +21,7 @@ createField: CreateField; #### Defined in -[createForm.tsx:16](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L16) +[packages/solid-form/src/createForm.tsx:16](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L16) *** @@ -33,7 +33,7 @@ Field: FieldComponent; #### Defined in -[createForm.tsx:15](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L15) +[packages/solid-form/src/createForm.tsx:15](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L15) *** @@ -49,11 +49,15 @@ Subscribe: (props) => Element; #### Parameters -• **props** +##### props -• **props.children**: `Element` \| (`state`) => `Element` +###### children -• **props.selector?** +`Element` \| (`state`) => `Element` + +###### selector + +(`state`) => `TSelected` #### Returns @@ -61,7 +65,7 @@ Subscribe: (props) => Element; #### Defined in -[createForm.tsx:20](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L20) +[packages/solid-form/src/createForm.tsx:20](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L20) *** @@ -77,7 +81,9 @@ useStore: (selector?) => () => TSelected; #### Parameters -• **selector?** +##### selector? + +(`state`) => `TSelected` #### Returns @@ -89,4 +95,4 @@ useStore: (selector?) => () => TSelected; #### Defined in -[createForm.tsx:17](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L17) +[packages/solid-form/src/createForm.tsx:17](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L17) diff --git a/docs/framework/solid/reference/type-aliases/createfield.md b/docs/framework/solid/reference/type-aliases/createfield.md index 321be9093..6c74e7fb9 100644 --- a/docs/framework/solid/reference/type-aliases/createfield.md +++ b/docs/framework/solid/reference/type-aliases/createfield.md @@ -25,7 +25,9 @@ type CreateField: (o ## Parameters -• **opts** +### opts + +() => `object` & `Omit`\<`CreateFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> ## Returns @@ -37,4 +39,4 @@ type CreateField: (o ## Defined in -[createField.tsx:29](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L29) +[packages/solid-form/src/createField.tsx:29](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L29) diff --git a/docs/framework/solid/reference/type-aliases/fieldcomponent.md b/docs/framework/solid/reference/type-aliases/fieldcomponent.md index bfa206357..d953d3f8e 100644 --- a/docs/framework/solid/reference/type-aliases/fieldcomponent.md +++ b/docs/framework/solid/reference/type-aliases/fieldcomponent.md @@ -28,10 +28,12 @@ type FieldComponent: , `"form"`\> +\} + +`Omit`\<`FieldComponentProps`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> ## Returns @@ -39,4 +41,4 @@ type FieldComponent: data.value?.firstName || '') +const lastName = computed(() => data.value?.lastName || '') -watchEffect(() => { - if (data.value) { - defaultValues.firstName = data.value.firstName; - defaultValues.lastName = data.value.lastName; - } +const defaultValues = reactive({ + firstName, + lastName }); const form = useForm({ diff --git a/docs/framework/vue/guides/basic-concepts.md b/docs/framework/vue/guides/basic-concepts.md index 79e07f06b..86a8a90f9 100644 --- a/docs/framework/vue/guides/basic-concepts.md +++ b/docs/framework/vue/guides/basic-concepts.md @@ -146,22 +146,25 @@ Example: ``` -## Validation Adapters +## Validation with Standard Schema Libraries -In addition to hand-rolled validation options, we also provide adapters like `@tanstack/zod-form-adapter`, `@tanstack/yup-form-adapter`, and `@tanstack/valibot-form-adapter` to enable usage with common schema validation tools like [Zod](https://zod.dev/), [Yup](https://github.com/jquense/yup), and [Valibot](https://valibot.dev/). +In addition to hand-rolled validation options, we also support the [Standard Schema](https://github.com/standard-schema/standard-schema) specification. -Example: +You can define a schema using any of the libraries implementing the specification and pass it to a form or field validator. + +Supported libraries include: + +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) ```vue + + +``` diff --git a/docs/framework/vue/guides/validation.md b/docs/framework/vue/guides/validation.md index a9aea2c5f..beb3f7504 100644 --- a/docs/framework/vue/guides/validation.md +++ b/docs/framework/vue/guides/validation.md @@ -322,31 +322,27 @@ This will debounce every async call with a 500ms delay. You can even override th This will run `onChangeAsync` every 1500ms while `onBlurAsync` will run every 500ms. -## Adapter-Based Validation (Zod, Yup, Valibot) +## Validation through Schema Libraries -While functions provide more flexibility and customization over your validation, they can be a bit verbose. To help solve this, there are libraries like [Valibot](https://valibot.dev/), [Yup](https://github.com/jquense/yup), and [Zod](https://zod.dev/) that provide schema-based validation to make shorthand and type-strict validation substantially easier. +While functions provide more flexibility and customization over your validation, they can be a bit verbose. To help solve this, there are libraries that provide schema-based validation to make shorthand and type-strict validation substantially easier. You can also define a single schema for your entire form and pass it to the form level, errors will be automatically propagated to the fields. -Luckily, we support all of these libraries through official adapters: +### Standard Schema Libraries -```bash -$ npm install @tanstack/zod-form-adapter zod -# or -$ npm install @tanstack/yup-form-adapter yup -# or -$ npm install @tanstack/valibot-form-adapter valibot -``` +TanStack Form natively supports all libraries following the [Standard Schema specification](https://github.com/standard-schema/standard-schema), most notably: +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) -Once done, we can add the adapter to the `validator` property on the form or field: +*Note:* make sure to use the latest version of the schema libraries as older versions might not support Standard Schema yet. + +To use schemas from these libraries you can pass them to the `validators` props as you would do with a custom function: ```vue @@ -355,7 +351,6 @@ const form = useForm({ ``` -These adapters also support async operations using the proper property names: +Async validations on form and field level are supported as well: ```vue ``` -### Form Level Adapter Validation +### Other Schema Libraries -You can also use the adapter at the form level: +We also support [Yup](https://github.com/jquense/yup) through an official adapter: -```typescript -import { zodValidator } from '@tanstack/zod-form-adapter' -import { z } from 'zod' +```bash +$ npm install @tanstack/yup-form-adapter yup +``` + +Once done, we can add the adapter to the `validator` property on the form or field: + +```vue + -```vue ``` -Will still display the error message from the form-level validation. - ## Preventing invalid forms from being submitted The `onChange`, `onBlur` etc... callbacks are also run when the form is submitted and the submission is blocked if the form is invalid. diff --git a/docs/framework/vue/reference/functions/field.md b/docs/framework/vue/reference/functions/field.md deleted file mode 100644 index b74d92e28..000000000 --- a/docs/framework/vue/reference/functions/field.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -id: Field -title: Field ---- - -# Function: Field() - -```ts -function Field(props): any -``` - -## Type Parameters - -• **TParentData** - -• **TName** *extends* `string` \| `number` - -• **TFieldValidator** *extends* `undefined` \| `Validator`\<`DeepValue`\<`TParentData`, `TName`\>, `unknown`\> = `undefined` - -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TParentData`, `unknown`\> = `undefined` - -• **TData** = `DeepValue`\<`TParentData`, `TName`\> - -## Parameters - -• **props**: `FieldApiOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> & `object` & `object` \| `object` - -## Returns - -`any` - -## Defined in - -[packages/vue-form/src/useField.tsx:162](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L162) diff --git a/docs/framework/vue/reference/functions/usefield.md b/docs/framework/vue/reference/functions/usefield.md index a9809222f..cc91f6941 100644 --- a/docs/framework/vue/reference/functions/usefield.md +++ b/docs/framework/vue/reference/functions/usefield.md @@ -23,7 +23,9 @@ function useField(op ## Parameters -• **opts**: `UseFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +### opts + +`UseFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> ## Returns @@ -38,7 +40,7 @@ readonly api: FieldApi>> = fieldState; +readonly state: Readonly, FieldState>> = fieldState; ``` ## Defined in diff --git a/docs/framework/vue/reference/functions/useform.md b/docs/framework/vue/reference/functions/useform.md index 6607abab8..d1767f45a 100644 --- a/docs/framework/vue/reference/functions/useform.md +++ b/docs/framework/vue/reference/functions/useform.md @@ -17,7 +17,9 @@ function useForm(opts?): FormApi +### opts? + +`FormOptions`\<`TFormData`, `TFormValidator`\> ## Returns diff --git a/docs/framework/vue/reference/functions/usestore.md b/docs/framework/vue/reference/functions/usestore.md new file mode 100644 index 000000000..1d5ad022f --- /dev/null +++ b/docs/framework/vue/reference/functions/usestore.md @@ -0,0 +1,66 @@ +--- +id: useStore +title: useStore +--- + +# Function: useStore() + +## Call Signature + +```ts +function useStore(store, selector?): Readonly> +``` + +### Type Parameters + +• **TState** + +• **TSelected** = `NoInfer`\<`TState`\> + +### Parameters + +#### store + +`Store`\<`TState`, `any`\> + +#### selector? + +(`state`) => `TSelected` + +### Returns + +`Readonly`\<`Ref`\<`TSelected`\>\> + +### Defined in + +node\_modules/.pnpm/@tanstack+vue-store@0.7.0\_vue@3.5.12\_typescript@5.7.2\_/node\_modules/@tanstack/vue-store/dist/esm/index.d.ts:8 + +## Call Signature + +```ts +function useStore(store, selector?): Readonly> +``` + +### Type Parameters + +• **TState** + +• **TSelected** = `NoInfer`\<`TState`\> + +### Parameters + +#### store + +`Derived`\<`TState`, `any`\> + +#### selector? + +(`state`) => `TSelected` + +### Returns + +`Readonly`\<`Ref`\<`TSelected`\>\> + +### Defined in + +node\_modules/.pnpm/@tanstack+vue-store@0.7.0\_vue@3.5.12\_typescript@5.7.2\_/node\_modules/@tanstack/vue-store/dist/esm/index.d.ts:9 diff --git a/docs/framework/vue/reference/index.md b/docs/framework/vue/reference/index.md index 8209605cb..27abe16df 100644 --- a/docs/framework/vue/reference/index.md +++ b/docs/framework/vue/reference/index.md @@ -15,8 +15,12 @@ title: "@tanstack/vue-form" - [FieldComponent](type-aliases/fieldcomponent.md) - [UseField](type-aliases/usefield.md) +## Variables + +- [Field](variables/field.md) + ## Functions -- [Field](functions/field.md) - [useField](functions/usefield.md) - [useForm](functions/useform.md) +- [useStore](functions/usestore.md) diff --git a/docs/framework/vue/reference/interfaces/vueformapi.md b/docs/framework/vue/reference/interfaces/vueformapi.md index b9afadef7..abe693ff5 100644 --- a/docs/framework/vue/reference/interfaces/vueformapi.md +++ b/docs/framework/vue/reference/interfaces/vueformapi.md @@ -37,11 +37,15 @@ Subscribe: (props, context) => any; #### Parameters -• **props** +##### props -• **props.selector?** +###### selector -• **context**: `SetupContext`\<`EmitsOptions`, `SlotsType`\<`object`\>\> +(`state`) => `TSelected` + +##### context + +`SetupContext`\<`EmitsOptions`, `SlotsType`\<`object`\>\> #### Returns @@ -68,7 +72,7 @@ useField: UseField; ### useStore() ```ts -useStore: (selector?) => Readonly>; +useStore: (selector?) => Readonly>; ``` #### Type Parameters @@ -77,11 +81,13 @@ useStore: (selector?) => Readonly>; #### Parameters -• **selector?** +##### selector? + +(`state`) => `TSelected` #### Returns -`Readonly`\<`Ref`\<`TSelected`\>\> +`Readonly`\<`Ref`\<`TSelected`, `TSelected`\>\> #### Defined in diff --git a/docs/framework/vue/reference/type-aliases/fieldcomponent.md b/docs/framework/vue/reference/type-aliases/fieldcomponent.md index 348616c97..332ca141c 100644 --- a/docs/framework/vue/reference/type-aliases/fieldcomponent.md +++ b/docs/framework/vue/reference/type-aliases/fieldcomponent.md @@ -25,9 +25,13 @@ type FieldComponent: , `"form"`\> +### fieldOptions -• **context**: `SetupContext`\<`object`, `SlotsType`\<`object`\>\> +`Omit`\<`FieldComponentProps`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> + +### context + +`SetupContext`\<`object`, `SlotsType`\<`object`\>\> ## Returns diff --git a/docs/framework/vue/reference/type-aliases/usefield.md b/docs/framework/vue/reference/type-aliases/usefield.md index a4d2ea847..e0b8ff373 100644 --- a/docs/framework/vue/reference/type-aliases/usefield.md +++ b/docs/framework/vue/reference/type-aliases/usefield.md @@ -25,7 +25,9 @@ type UseField: (opts ## Parameters -• **opts**: `Omit`\<`UseFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> +### opts + +`Omit`\<`UseFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> ## Returns diff --git a/docs/framework/vue/reference/variables/field.md b/docs/framework/vue/reference/variables/field.md new file mode 100644 index 000000000..9336d31d3 --- /dev/null +++ b/docs/framework/vue/reference/variables/field.md @@ -0,0 +1,24 @@ +--- +id: Field +title: Field +--- + +# Variable: Field() + +```ts +const Field: (props) => CreateComponentPublicInstanceWithMixins & object & {} | {}, object, object, object, object, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, PublicProps, object, false, object, object, object, object, string, object, any, ComponentProvideOptions, OptionTypesType, object & FieldApiOptions & { mode?: "value" | ... 1 more ... | undefined; } & ({ ...; } | { ...; }), object, object, object, object, object>; +``` + +## Parameters + +### props + +FieldApiOptions\ & \{ mode?: "value" \| ... 1 more ... \| undefined; \} & (\{ ...; \} \| \{ ...; \}) & `VNodeProps` & `AllowedComponentProps` & `ComponentCustomProps` + +## Returns + +`CreateComponentPublicInstanceWithMixins`\<`FieldApiOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> & `object` & \{\} \| \{\}, `object`, `object`, `object`, `object`, `ComponentOptionsMixin`, `ComponentOptionsMixin`, `EmitsOptions`, `PublicProps`, `object`, `false`, `object`, `object`, `object`, `object`, `string`, `object`, `any`, `ComponentProvideOptions`, `OptionTypesType`\<`object`, `object`, `object`, `object`, `object`, `object`\>, `object` & FieldApiOptions\ & \{ mode?: "value" \| ... 1 more ... \| undefined; \} & (\{ ...; \} \| \{ ...; \}), `object`, `object`, `object`, `object`, `object`\> + +## Defined in + +[packages/vue-form/src/useField.tsx:162](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L162) diff --git a/docs/reference/classes/fieldapi.md b/docs/reference/classes/fieldapi.md index 80c08c0cc..ee7290043 100644 --- a/docs/reference/classes/fieldapi.md +++ b/docs/reference/classes/fieldapi.md @@ -37,7 +37,9 @@ Initializes a new `FieldApi` instance. #### Parameters -• **opts**: [`FieldApiOptions`](../interfaces/fieldapioptions.md)\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +##### opts + +[`FieldApiOptions`](../interfaces/fieldapioptions.md)\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> #### Returns @@ -45,7 +47,7 @@ Initializes a new `FieldApi` instance. #### Defined in -[packages/form-core/src/FieldApi.ts:439](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L439) +[packages/form-core/src/FieldApi.ts:477](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L477) ## Properties @@ -59,7 +61,7 @@ A reference to the form API instance. #### Defined in -[packages/form-core/src/FieldApi.ts:402](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L402) +[packages/form-core/src/FieldApi.ts:441](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L441) *** @@ -73,7 +75,7 @@ The field name. #### Defined in -[packages/form-core/src/FieldApi.ts:412](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L412) +[packages/form-core/src/FieldApi.ts:451](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L451) *** @@ -87,35 +89,53 @@ The field options. #### Defined in -[packages/form-core/src/FieldApi.ts:416](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L416) +[packages/form-core/src/FieldApi.ts:455](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L455) *** -### state +### store ```ts -state: FieldState; +store: Derived, readonly any[]>; ``` -The current field state. +The field state store. #### Defined in -[packages/form-core/src/FieldApi.ts:430](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L430) +[packages/form-core/src/FieldApi.ts:465](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L465) *** -### store +### timeoutIds ```ts -store: Store, (cb) => FieldState>; +timeoutIds: Record; ``` -The field state store. +#### Defined in + +[packages/form-core/src/FieldApi.ts:472](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L472) + +## Accessors + +### state + +#### Get Signature + +```ts +get state(): FieldState +``` + +The current field state. + +##### Returns + +[`FieldState`](../type-aliases/fieldstate.md)\<`TData`\> #### Defined in -[packages/form-core/src/FieldApi.ts:426](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L426) +[packages/form-core/src/FieldApi.ts:469](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L469) ## Methods @@ -133,7 +153,7 @@ Gets the field information object. #### Defined in -[packages/form-core/src/FieldApi.ts:657](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L657) +[packages/form-core/src/FieldApi.ts:672](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L672) *** @@ -143,15 +163,13 @@ Gets the field information object. getMeta(): FieldMeta ``` -Gets the current field metadata. - #### Returns [`FieldMeta`](../type-aliases/fieldmeta.md) #### Defined in -[packages/form-core/src/FieldApi.ts:635](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L635) +[packages/form-core/src/FieldApi.ts:661](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L661) *** @@ -173,7 +191,7 @@ Use `field.state.value` instead. #### Defined in -[packages/form-core/src/FieldApi.ts:615](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L615) +[packages/form-core/src/FieldApi.ts:643](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L643) *** @@ -191,7 +209,7 @@ Handles the blur event. #### Defined in -[packages/form-core/src/FieldApi.ts:1016](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1016) +[packages/form-core/src/FieldApi.ts:1024](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1024) *** @@ -205,7 +223,9 @@ Handles the change event. #### Parameters -• **updater**: [`Updater`](../type-aliases/updater.md)\<`TData`\> +##### updater + +[`Updater`](../type-aliases/updater.md)\<`TData`\> #### Returns @@ -213,7 +233,7 @@ Handles the change event. #### Defined in -[packages/form-core/src/FieldApi.ts:1009](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1009) +[packages/form-core/src/FieldApi.ts:1017](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1017) *** @@ -230,11 +250,17 @@ Inserts a value at the specified index, shifting the subsequent values to the ri #### Parameters -• **index**: `number` +##### index + +`number` -• **value**: `TData` *extends* `any`[] ? `TData`\<`TData`\>\[`number`\] : `never` +##### value -• **opts?**: `UpdateMetaOptions` +`TData` *extends* `any`[] ? `TData`\<`TData`\>\[`number`\] : `never` + +##### opts? + +`UpdateMetaOptions` #### Returns @@ -242,7 +268,7 @@ Inserts a value at the specified index, shifting the subsequent values to the ri #### Defined in -[packages/form-core/src/FieldApi.ts:670](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L670) +[packages/form-core/src/FieldApi.ts:685](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L685) *** @@ -264,7 +290,7 @@ Mounts the field instance to the form. #### Defined in -[packages/form-core/src/FieldApi.ts:530](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L530) +[packages/form-core/src/FieldApi.ts:567](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L567) *** @@ -281,11 +307,17 @@ Moves the value at the first specified index to the second specified index. #### Parameters -• **aIndex**: `number` +##### aIndex + +`number` -• **bIndex**: `number` +##### bIndex -• **opts?**: `UpdateMetaOptions` +`number` + +##### opts? + +`UpdateMetaOptions` #### Returns @@ -293,7 +325,7 @@ Moves the value at the first specified index to the second specified index. #### Defined in -[packages/form-core/src/FieldApi.ts:700](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L700) +[packages/form-core/src/FieldApi.ts:715](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L715) *** @@ -307,9 +339,13 @@ Pushes a new value to the field. #### Parameters -• **value**: `TData` *extends* `any`[] ? `TData`\<`TData`\>\[`number`\] : `never` +##### value + +`TData` *extends* `any`[] ? `TData`\<`TData`\>\[`number`\] : `never` -• **opts?**: `UpdateMetaOptions` +##### opts? + +`UpdateMetaOptions` #### Returns @@ -317,7 +353,7 @@ Pushes a new value to the field. #### Defined in -[packages/form-core/src/FieldApi.ts:662](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L662) +[packages/form-core/src/FieldApi.ts:677](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L677) *** @@ -331,9 +367,13 @@ Removes a value at the specified index. #### Parameters -• **index**: `number` +##### index + +`number` + +##### opts? -• **opts?**: `UpdateMetaOptions` +`UpdateMetaOptions` #### Returns @@ -341,7 +381,7 @@ Removes a value at the specified index. #### Defined in -[packages/form-core/src/FieldApi.ts:688](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L688) +[packages/form-core/src/FieldApi.ts:703](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L703) *** @@ -358,11 +398,17 @@ Replaces a value at the specified index. #### Parameters -• **index**: `number` +##### index + +`number` + +##### value + +`TData` *extends* `any`[] ? `TData`\<`TData`\>\[`number`\] : `never` -• **value**: `TData` *extends* `any`[] ? `TData`\<`TData`\>\[`number`\] : `never` +##### opts? -• **opts?**: `UpdateMetaOptions` +`UpdateMetaOptions` #### Returns @@ -370,7 +416,7 @@ Replaces a value at the specified index. #### Defined in -[packages/form-core/src/FieldApi.ts:679](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L679) +[packages/form-core/src/FieldApi.ts:694](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L694) *** @@ -384,7 +430,9 @@ Updates the field's errorMap #### Parameters -• **errorMap**: `ValidationErrorMap` +##### errorMap + +`ValidationErrorMap` #### Returns @@ -392,7 +440,7 @@ Updates the field's errorMap #### Defined in -[packages/form-core/src/FieldApi.ts:1031](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1031) +[packages/form-core/src/FieldApi.ts:1044](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1044) *** @@ -406,7 +454,9 @@ Sets the field metadata. #### Parameters -• **updater**: [`Updater`](../type-aliases/updater.md)\<[`FieldMeta`](../type-aliases/fieldmeta.md)\> +##### updater + +[`Updater`](../type-aliases/updater.md)\<[`FieldMeta`](../type-aliases/fieldmeta.md)\> #### Returns @@ -414,7 +464,7 @@ Sets the field metadata. #### Defined in -[packages/form-core/src/FieldApi.ts:651](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L651) +[packages/form-core/src/FieldApi.ts:666](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L666) *** @@ -428,9 +478,13 @@ Sets the field value and run the `change` validator. #### Parameters -• **updater**: [`Updater`](../type-aliases/updater.md)\<`TData`\> +##### updater -• **options?**: `UpdateMetaOptions` +[`Updater`](../type-aliases/updater.md)\<`TData`\> + +##### options? + +`UpdateMetaOptions` #### Returns @@ -438,7 +492,7 @@ Sets the field value and run the `change` validator. #### Defined in -[packages/form-core/src/FieldApi.ts:622](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L622) +[packages/form-core/src/FieldApi.ts:650](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L650) *** @@ -455,11 +509,17 @@ Swaps the values at the specified indices. #### Parameters -• **aIndex**: `number` +##### aIndex + +`number` -• **bIndex**: `number` +##### bIndex -• **opts?**: `UpdateMetaOptions` +`number` + +##### opts? + +`UpdateMetaOptions` #### Returns @@ -467,7 +527,7 @@ Swaps the values at the specified indices. #### Defined in -[packages/form-core/src/FieldApi.ts:694](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L694) +[packages/form-core/src/FieldApi.ts:709](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L709) *** @@ -481,7 +541,9 @@ Updates the field instance with new options. #### Parameters -• **opts**: [`FieldApiOptions`](../interfaces/fieldapioptions.md)\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +##### opts + +[`FieldApiOptions`](../interfaces/fieldapioptions.md)\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> #### Returns @@ -489,7 +551,7 @@ Updates the field instance with new options. #### Defined in -[packages/form-core/src/FieldApi.ts:578](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L578) +[packages/form-core/src/FieldApi.ts:606](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L606) *** @@ -503,7 +565,9 @@ Validates the field value. #### Parameters -• **cause**: `ValidationCause` +##### cause + +`ValidationCause` #### Returns @@ -511,4 +575,4 @@ Validates the field value. #### Defined in -[packages/form-core/src/FieldApi.ts:970](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L970) +[packages/form-core/src/FieldApi.ts:989](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L989) diff --git a/docs/reference/classes/formapi.md b/docs/reference/classes/formapi.md index 295200fbe..d9b818804 100644 --- a/docs/reference/classes/formapi.md +++ b/docs/reference/classes/formapi.md @@ -29,7 +29,9 @@ Constructs a new `FormApi` instance with the given form options. #### Parameters -• **opts?**: [`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TFormValidator`\> +##### opts? + +[`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TFormValidator`\> #### Returns @@ -37,10 +39,22 @@ Constructs a new `FormApi` instance with the given form options. #### Defined in -[packages/form-core/src/FormApi.ts:386](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L386) +[packages/form-core/src/FormApi.ts:389](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L389) ## Properties +### baseStore + +```ts +baseStore: Store, (cb) => BaseFormState>; +``` + +#### Defined in + +[packages/form-core/src/FormApi.ts:368](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L368) + +*** + ### fieldInfo ```ts @@ -51,7 +65,19 @@ A record of field information for each field in the form. #### Defined in -[packages/form-core/src/FormApi.ts:375](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L375) +[packages/form-core/src/FormApi.ts:374](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L374) + +*** + +### fieldMetaDerived + +```ts +fieldMetaDerived: Derived ? PrefixTupleAccessor, AllowedIndexes, never>, []> : TFormData extends any[] ? PrefixArrayAccessor, [any]> : TFormData extends Date ? never : TFormData extends object ? PrefixObjectAccessor, []> : TFormData extends string | number | bigint | boolean ? "" : never, FieldMeta>, readonly any[]>; +``` + +#### Defined in + +[packages/form-core/src/FormApi.ts:369](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L369) *** @@ -65,39 +91,37 @@ The options for the form. #### Defined in -[packages/form-core/src/FormApi.ts:359](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L359) +[packages/form-core/src/FormApi.ts:367](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L367) *** -### state +### store ```ts -state: FormState; +store: Derived, readonly any[]>; ``` -The current state of the form. - -**Note:** -Do not use `state` directly, as it is not reactive. -Please use form.useStore() utility to subscribe to state - #### Defined in -[packages/form-core/src/FormApi.ts:371](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L371) +[packages/form-core/src/FormApi.ts:370](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L370) -*** +## Accessors -### store +### state + +#### Get Signature ```ts -store: Store, (cb) => FormState>; +get state(): FormState ``` -A [TanStack Store instance](https://tanstack.com/store/latest/docs/reference/Store) that keeps track of the form's state. +##### Returns + +[`FormState`](../type-aliases/formstate.md)\<`TFormData`\> #### Defined in -[packages/form-core/src/FormApi.ts:363](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L363) +[packages/form-core/src/FormApi.ts:377](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L377) ## Methods @@ -113,7 +137,9 @@ deleteField(field): void #### Parameters -• **field**: `TField` +##### field + +`TField` #### Returns @@ -121,7 +147,7 @@ deleteField(field): void #### Defined in -[packages/form-core/src/FormApi.ts:1082](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1082) +[packages/form-core/src/FormApi.ts:1182](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1182) *** @@ -139,7 +165,9 @@ Gets the field info of the specified field. #### Parameters -• **field**: `TField` +##### field + +`TField` #### Returns @@ -147,7 +175,7 @@ Gets the field info of the specified field. #### Defined in -[packages/form-core/src/FormApi.ts:998](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L998) +[packages/form-core/src/FormApi.ts:1091](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1091) *** @@ -165,7 +193,9 @@ Gets the metadata of the specified field. #### Parameters -• **field**: `TField` +##### field + +`TField` #### Returns @@ -173,7 +203,7 @@ Gets the metadata of the specified field. #### Defined in -[packages/form-core/src/FormApi.ts:989](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L989) +[packages/form-core/src/FormApi.ts:1082](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1082) *** @@ -191,7 +221,9 @@ Gets the value of the specified field. #### Parameters -• **field**: `TField` +##### field + +`TField` #### Returns @@ -199,7 +231,7 @@ Gets the value of the specified field. #### Defined in -[packages/form-core/src/FormApi.ts:982](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L982) +[packages/form-core/src/FormApi.ts:1075](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1075) *** @@ -217,7 +249,7 @@ Handles the form submission, performs validation, and calls the appropriate onSu #### Defined in -[packages/form-core/src/FormApi.ts:922](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L922) +[packages/form-core/src/FormApi.ts:1016](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1016) *** @@ -239,13 +271,21 @@ Inserts a value into an array field at the specified index, shifting the subsequ #### Parameters -• **field**: `TField` +##### field + +`TField` + +##### index -• **index**: `number` +`number` -• **value**: [`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\> *extends* `any`[] ? `any`[] & [`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\>\[`number`\] : `never` +##### value -• **opts?**: `UpdateMetaOptions` +[`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\> *extends* `any`[] ? `any`[] & [`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\>\[`number`\] : `never` + +##### opts? + +`UpdateMetaOptions` #### Returns @@ -253,23 +293,27 @@ Inserts a value into an array field at the specified index, shifting the subsequ #### Defined in -[packages/form-core/src/FormApi.ts:1114](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1114) +[packages/form-core/src/FormApi.ts:1214](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1214) *** ### mount() ```ts -mount(): void +mount(): () => void ``` #### Returns +`Function` + +##### Returns + `void` #### Defined in -[packages/form-core/src/FormApi.ts:499](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L499) +[packages/form-core/src/FormApi.ts:595](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L595) *** @@ -291,13 +335,21 @@ Moves the value at the first specified index to the second specified index withi #### Parameters -• **field**: `TField` +##### field + +`TField` -• **index1**: `number` +##### index1 -• **index2**: `number` +`number` -• **opts?**: `UpdateMetaOptions` +##### index2 + +`number` + +##### opts? + +`UpdateMetaOptions` #### Returns @@ -305,7 +357,7 @@ Moves the value at the first specified index to the second specified index withi #### Defined in -[packages/form-core/src/FormApi.ts:1232](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1232) +[packages/form-core/src/FormApi.ts:1332](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1332) *** @@ -326,11 +378,17 @@ Pushes a value into an array field. #### Parameters -• **field**: `TField` +##### field + +`TField` + +##### value + +[`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\> *extends* `any`[] ? `any`[] & [`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\>\[`number`\] : `never` -• **value**: [`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\> *extends* `any`[] ? `any`[] & [`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\>\[`number`\] : `never` +##### opts? -• **opts?**: `UpdateMetaOptions` +`UpdateMetaOptions` #### Returns @@ -338,7 +396,7 @@ Pushes a value into an array field. #### Defined in -[packages/form-core/src/FormApi.ts:1096](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1096) +[packages/form-core/src/FormApi.ts:1196](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1196) *** @@ -359,11 +417,17 @@ Removes a value from an array field at the specified index. #### Parameters -• **field**: `TField` +##### field -• **index**: `number` +`TField` -• **opts?**: `UpdateMetaOptions` +##### index + +`number` + +##### opts? + +`UpdateMetaOptions` #### Returns @@ -371,7 +435,7 @@ Removes a value from an array field at the specified index. #### Defined in -[packages/form-core/src/FormApi.ts:1167](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1167) +[packages/form-core/src/FormApi.ts:1267](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1267) *** @@ -393,13 +457,21 @@ Replaces a value into an array field at the specified index. #### Parameters -• **field**: `TField` +##### field + +`TField` + +##### index -• **index**: `number` +`number` -• **value**: [`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\> *extends* `any`[] ? `any`[] & [`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\>\[`number`\] : `never` +##### value -• **opts?**: `UpdateMetaOptions` +[`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\> *extends* `any`[] ? `any`[] & [`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\>\[`number`\] : `never` + +##### opts? + +`UpdateMetaOptions` #### Returns @@ -407,17 +479,34 @@ Replaces a value into an array field at the specified index. #### Defined in -[packages/form-core/src/FormApi.ts:1141](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1141) +[packages/form-core/src/FormApi.ts:1241](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1241) *** ### reset() ```ts -reset(): void +reset(values?, opts?): void ``` Resets the form state to the default values. +If values are provided, the form will be reset to those values instead and the default values will be updated. + +#### Parameters + +##### values? + +`TFormData` + +Optional values to reset the form to. + +##### opts? + +Optional options to control the reset behavior. + +###### keepDefaultValues + +`boolean` #### Returns @@ -425,7 +514,7 @@ Resets the form state to the default values. #### Defined in -[packages/form-core/src/FormApi.ts:562](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L562) +[packages/form-core/src/FormApi.ts:656](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L656) *** @@ -441,7 +530,9 @@ resetFieldMeta(fieldMeta): Record #### Parameters -• **fieldMeta**: `Record`\<`TField`, [`FieldMeta`](../type-aliases/fieldmeta.md)\> +##### fieldMeta + +`Record`\<`TField`, [`FieldMeta`](../type-aliases/fieldmeta.md)\> #### Returns @@ -449,7 +540,7 @@ resetFieldMeta(fieldMeta): Record #### Defined in -[packages/form-core/src/FormApi.ts:1032](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1032) +[packages/form-core/src/FormApi.ts:1128](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1128) *** @@ -463,7 +554,9 @@ Updates the form's errorMap #### Parameters -• **errorMap**: `ValidationErrorMap` +##### errorMap + +`ValidationErrorMap` #### Returns @@ -471,7 +564,7 @@ Updates the form's errorMap #### Defined in -[packages/form-core/src/FormApi.ts:1256](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1256) +[packages/form-core/src/FormApi.ts:1356](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1356) *** @@ -489,9 +582,13 @@ Updates the metadata of the specified field. #### Parameters -• **field**: `TField` +##### field + +`TField` -• **updater**: [`Updater`](../type-aliases/updater.md)\<[`FieldMeta`](../type-aliases/fieldmeta.md)\> +##### updater + +[`Updater`](../type-aliases/updater.md)\<[`FieldMeta`](../type-aliases/fieldmeta.md)\> #### Returns @@ -499,7 +596,7 @@ Updates the metadata of the specified field. #### Defined in -[packages/form-core/src/FormApi.ts:1017](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1017) +[packages/form-core/src/FormApi.ts:1110](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1110) *** @@ -520,11 +617,17 @@ Sets the value of the specified field and optionally updates the touched state. #### Parameters -• **field**: `TField` +##### field + +`TField` + +##### updater -• **updater**: [`Updater`](../type-aliases/updater.md)\<[`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\>\> +[`Updater`](../type-aliases/updater.md)\<[`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\>\> -• **opts?**: `UpdateMetaOptions` +##### opts? + +`UpdateMetaOptions` #### Returns @@ -532,7 +635,7 @@ Sets the value of the specified field and optionally updates the touched state. #### Defined in -[packages/form-core/src/FormApi.ts:1056](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1056) +[packages/form-core/src/FormApi.ts:1152](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1152) *** @@ -554,13 +657,21 @@ Swaps the values at the specified indices within an array field. #### Parameters -• **field**: `TField` +##### field + +`TField` -• **index1**: `number` +##### index1 -• **index2**: `number` +`number` -• **opts?**: `UpdateMetaOptions` +##### index2 + +`number` + +##### opts? + +`UpdateMetaOptions` #### Returns @@ -568,7 +679,7 @@ Swaps the values at the specified indices within an array field. #### Defined in -[packages/form-core/src/FormApi.ts:1206](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1206) +[packages/form-core/src/FormApi.ts:1306](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1306) *** @@ -582,7 +693,9 @@ Updates the form options and form state. #### Parameters -• **options?**: [`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TFormValidator`\> +##### options? + +[`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TFormValidator`\> #### Returns @@ -590,7 +703,7 @@ Updates the form options and form state. #### Defined in -[packages/form-core/src/FormApi.ts:522](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L522) +[packages/form-core/src/FormApi.ts:612](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L612) *** @@ -600,11 +713,13 @@ Updates the form options and form state. validateAllFields(cause): Promise ``` -Validates all fields in the form using the correct handlers for a given validation type. +Validates form and all fields in using the correct handlers for a given validation cause. #### Parameters -• **cause**: `ValidationCause` +##### cause + +`ValidationCause` #### Returns @@ -612,7 +727,7 @@ Validates all fields in the form using the correct handlers for a given validati #### Defined in -[packages/form-core/src/FormApi.ts:577](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L577) +[packages/form-core/src/FormApi.ts:682](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L682) *** @@ -633,11 +748,17 @@ Validates the children of a specified array in the form starting from a given in #### Parameters -• **field**: `TField` +##### field -• **index**: `number` +`TField` -• **cause**: `ValidationCause` +##### index + +`number` + +##### cause + +`ValidationCause` #### Returns @@ -645,7 +766,7 @@ Validates the children of a specified array in the form starting from a given in #### Defined in -[packages/form-core/src/FormApi.ts:610](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L610) +[packages/form-core/src/FormApi.ts:710](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L710) *** @@ -663,9 +784,13 @@ Validates a specified field in the form using the correct handlers for a given v #### Parameters -• **field**: `TField` +##### field + +`TField` + +##### cause -• **cause**: `ValidationCause` +`ValidationCause` #### Returns @@ -673,4 +798,4 @@ Validates a specified field in the form using the correct handlers for a given v #### Defined in -[packages/form-core/src/FormApi.ts:649](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L649) +[packages/form-core/src/FormApi.ts:749](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L749) diff --git a/docs/reference/functions/formoptions.md b/docs/reference/functions/formoptions.md index 66f6aa695..ba679302f 100644 --- a/docs/reference/functions/formoptions.md +++ b/docs/reference/functions/formoptions.md @@ -17,7 +17,9 @@ function formOptions(defaultOpts?): undefined | FormO ## Parameters -• **defaultOpts?**: [`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TFormValidator`\> +### defaultOpts? + +[`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TFormValidator`\> ## Returns diff --git a/docs/reference/functions/isstandardschemavalidator.md b/docs/reference/functions/isstandardschemavalidator.md new file mode 100644 index 000000000..f9e78ae3b --- /dev/null +++ b/docs/reference/functions/isstandardschemavalidator.md @@ -0,0 +1,24 @@ +--- +id: isStandardSchemaValidator +title: isStandardSchemaValidator +--- + +# Function: isStandardSchemaValidator() + +```ts +function isStandardSchemaValidator(validator): validator is StandardSchemaV1 +``` + +## Parameters + +### validator + +`unknown` + +## Returns + +`validator is StandardSchemaV1` + +## Defined in + +[packages/form-core/src/standardSchemaValidator.ts:86](https://github.com/TanStack/form/blob/main/packages/form-core/src/standardSchemaValidator.ts#L86) diff --git a/docs/reference/functions/mergeform.md b/docs/reference/functions/mergeform.md index 395c40c15..d771a7bf3 100644 --- a/docs/reference/functions/mergeform.md +++ b/docs/reference/functions/mergeform.md @@ -17,9 +17,13 @@ function mergeForm(baseForm, state): FormApi, `NoInfer`\<`TFormValidator`\>\> +### baseForm -• **state**: `Partial`\<[`FormState`](../type-aliases/formstate.md)\<`TFormData`\>\> +[`FormApi`](../classes/formapi.md)\<`NoInfer`\<`TFormData`\>, `NoInfer`\<`TFormValidator`\>\> + +### state + +`Partial`\<[`FormState`](../type-aliases/formstate.md)\<`TFormData`\>\> ## Returns @@ -27,4 +31,4 @@ function mergeForm(baseForm, state): FormApi> +``` + +## Parameters + +### params + +`Params` = `{}` + +## Returns + +`Validator`\<`unknown`, [`StandardSchemaV1`](../type-aliases/standardschemav1.md)\<`any`, `any`\>\> + +## Defined in + +[packages/form-core/src/standardSchemaValidator.ts:48](https://github.com/TanStack/form/blob/main/packages/form-core/src/standardSchemaValidator.ts#L48) diff --git a/docs/reference/index.md b/docs/reference/index.md index 1ff82aa4a..6221bdca0 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -13,6 +13,7 @@ title: "@tanstack/form-core" ## Interfaces - [FieldApiOptions](interfaces/fieldapioptions.md) +- [FieldListeners](interfaces/fieldlisteners.md) - [FieldOptions](interfaces/fieldoptions.md) - [FieldValidators](interfaces/fieldvalidators.md) - [FormOptions](interfaces/formoptions.md) @@ -20,15 +21,20 @@ title: "@tanstack/form-core" ## Type Aliases +- [BaseFormState](type-aliases/baseformstate.md) - [DeepKeys](type-aliases/deepkeys.md) - [DeepValue](type-aliases/deepvalue.md) +- [DerivedFormState](type-aliases/derivedformstate.md) - [FieldInfo](type-aliases/fieldinfo.md) - [FieldMeta](type-aliases/fieldmeta.md) +- [FieldMetaBase](type-aliases/fieldmetabase.md) +- [FieldMetaDerived](type-aliases/fieldmetaderived.md) - [FieldsErrorMapFromValidator](type-aliases/fieldserrormapfromvalidator.md) - [FieldState](type-aliases/fieldstate.md) - [FormState](type-aliases/formstate.md) - [FormValidateFn](type-aliases/formvalidatefn.md) - [FormValidator](type-aliases/formvalidator.md) +- [StandardSchemaV1](type-aliases/standardschemav1.md) - [Updater](type-aliases/updater.md) - [UpdaterFn](type-aliases/updaterfn.md) - [ValidationError](type-aliases/validationerror.md) @@ -38,4 +44,6 @@ title: "@tanstack/form-core" ## Functions - [formOptions](functions/formoptions.md) +- [isStandardSchemaValidator](functions/isstandardschemavalidator.md) - [mergeForm](functions/mergeform.md) +- [standardSchemaValidator](functions/standardschemavalidator.md) diff --git a/docs/reference/interfaces/fieldapioptions.md b/docs/reference/interfaces/fieldapioptions.md index 8f583b4e0..43a394b83 100644 --- a/docs/reference/interfaces/fieldapioptions.md +++ b/docs/reference/interfaces/fieldapioptions.md @@ -39,7 +39,7 @@ If `true`, always run async validation, even if there are errors emitted during #### Defined in -[packages/form-core/src/FieldApi.ts:287](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L287) +[packages/form-core/src/FieldApi.ts:311](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L311) *** @@ -57,7 +57,7 @@ The default time to debounce async validation if there is not a more specific de #### Defined in -[packages/form-core/src/FieldApi.ts:283](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L283) +[packages/form-core/src/FieldApi.ts:307](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L307) *** @@ -75,7 +75,7 @@ An optional object with default metadata for the field. #### Defined in -[packages/form-core/src/FieldApi.ts:305](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L305) +[packages/form-core/src/FieldApi.ts:329](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L329) *** @@ -93,7 +93,7 @@ An optional default value for the field. #### Defined in -[packages/form-core/src/FieldApi.ts:279](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L279) +[packages/form-core/src/FieldApi.ts:303](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L303) *** @@ -105,7 +105,25 @@ form: FormApi; #### Defined in -[packages/form-core/src/FieldApi.ts:328](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L328) +[packages/form-core/src/FieldApi.ts:362](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L362) + +*** + +### listeners? + +```ts +optional listeners: FieldListeners; +``` + +A list of listeners which attach to the corresponding events + +#### Inherited from + +[`FieldOptions`](fieldoptions.md).[`listeners`](FieldOptions.md#listeners) + +#### Defined in + +[packages/form-core/src/FieldApi.ts:333](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L333) *** @@ -123,7 +141,7 @@ The field name. The type will be `DeepKeys` to ensure your name is #### Defined in -[packages/form-core/src/FieldApi.ts:275](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L275) +[packages/form-core/src/FieldApi.ts:299](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L299) *** @@ -141,7 +159,7 @@ A validator provided by an extension, like `yupValidator` from `@tanstack/yup-fo #### Defined in -[packages/form-core/src/FieldApi.ts:291](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L291) +[packages/form-core/src/FieldApi.ts:315](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L315) *** @@ -159,4 +177,4 @@ A list of validators to pass to the field #### Defined in -[packages/form-core/src/FieldApi.ts:295](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L295) +[packages/form-core/src/FieldApi.ts:319](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L319) diff --git a/docs/reference/interfaces/fieldlisteners.md b/docs/reference/interfaces/fieldlisteners.md new file mode 100644 index 000000000..937c14c6e --- /dev/null +++ b/docs/reference/interfaces/fieldlisteners.md @@ -0,0 +1,66 @@ +--- +id: FieldListeners +title: FieldListeners +--- + +# Interface: FieldListeners\ + +## Type Parameters + +• **TParentData** + +• **TName** *extends* [`DeepKeys`](../type-aliases/deepkeys.md)\<`TParentData`\> + +• **TFieldValidator** *extends* `Validator`\<[`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\>, `unknown`\> \| `undefined` = `undefined` + +• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` + +• **TData** *extends* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> = [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> + +## Properties + +### onBlur? + +```ts +optional onBlur: FieldListenerFn; +``` + +#### Defined in + +[packages/form-core/src/FieldApi.ts:259](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L259) + +*** + +### onChange? + +```ts +optional onChange: FieldListenerFn; +``` + +#### Defined in + +[packages/form-core/src/FieldApi.ts:252](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L252) + +*** + +### onMount? + +```ts +optional onMount: FieldListenerFn; +``` + +#### Defined in + +[packages/form-core/src/FieldApi.ts:266](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L266) + +*** + +### onSubmit? + +```ts +optional onSubmit: FieldListenerFn; +``` + +#### Defined in + +[packages/form-core/src/FieldApi.ts:273](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L273) diff --git a/docs/reference/interfaces/fieldoptions.md b/docs/reference/interfaces/fieldoptions.md index a4103fe25..b4044eeab 100644 --- a/docs/reference/interfaces/fieldoptions.md +++ b/docs/reference/interfaces/fieldoptions.md @@ -35,7 +35,7 @@ If `true`, always run async validation, even if there are errors emitted during #### Defined in -[packages/form-core/src/FieldApi.ts:287](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L287) +[packages/form-core/src/FieldApi.ts:311](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L311) *** @@ -49,7 +49,7 @@ The default time to debounce async validation if there is not a more specific de #### Defined in -[packages/form-core/src/FieldApi.ts:283](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L283) +[packages/form-core/src/FieldApi.ts:307](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L307) *** @@ -63,7 +63,7 @@ An optional object with default metadata for the field. #### Defined in -[packages/form-core/src/FieldApi.ts:305](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L305) +[packages/form-core/src/FieldApi.ts:329](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L329) *** @@ -77,7 +77,21 @@ An optional default value for the field. #### Defined in -[packages/form-core/src/FieldApi.ts:279](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L279) +[packages/form-core/src/FieldApi.ts:303](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L303) + +*** + +### listeners? + +```ts +optional listeners: FieldListeners; +``` + +A list of listeners which attach to the corresponding events + +#### Defined in + +[packages/form-core/src/FieldApi.ts:333](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L333) *** @@ -91,7 +105,7 @@ The field name. The type will be `DeepKeys` to ensure your name is #### Defined in -[packages/form-core/src/FieldApi.ts:275](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L275) +[packages/form-core/src/FieldApi.ts:299](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L299) *** @@ -105,7 +119,7 @@ A validator provided by an extension, like `yupValidator` from `@tanstack/yup-fo #### Defined in -[packages/form-core/src/FieldApi.ts:291](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L291) +[packages/form-core/src/FieldApi.ts:315](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L315) *** @@ -119,4 +133,4 @@ A list of validators to pass to the field #### Defined in -[packages/form-core/src/FieldApi.ts:295](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L295) +[packages/form-core/src/FieldApi.ts:319](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L319) diff --git a/docs/reference/interfaces/fieldvalidators.md b/docs/reference/interfaces/fieldvalidators.md index 57f9f54c2..e3770d3f8 100644 --- a/docs/reference/interfaces/fieldvalidators.md +++ b/docs/reference/interfaces/fieldvalidators.md @@ -36,7 +36,7 @@ z.string().min(1) // if `zodAdapter` is passed #### Defined in -[packages/form-core/src/FieldApi.ts:199](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L199) +[packages/form-core/src/FieldApi.ts:182](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L182) *** @@ -57,7 +57,7 @@ z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) // #### Defined in -[packages/form-core/src/FieldApi.ts:212](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L212) +[packages/form-core/src/FieldApi.ts:195](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L195) *** @@ -73,7 +73,7 @@ If set to a number larger than 0, will debounce the async validation event by th #### Defined in -[packages/form-core/src/FieldApi.ts:225](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L225) +[packages/form-core/src/FieldApi.ts:208](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L208) *** @@ -87,7 +87,7 @@ An optional list of field names that should trigger this field's `onBlur` and `o #### Defined in -[packages/form-core/src/FieldApi.ts:229](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L229) +[packages/form-core/src/FieldApi.ts:212](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L212) *** @@ -108,7 +108,7 @@ z.string().min(1) // if `zodAdapter` is passed #### Defined in -[packages/form-core/src/FieldApi.ts:163](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L163) +[packages/form-core/src/FieldApi.ts:146](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L146) *** @@ -129,7 +129,7 @@ z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) // #### Defined in -[packages/form-core/src/FieldApi.ts:176](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L176) +[packages/form-core/src/FieldApi.ts:159](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L159) *** @@ -145,7 +145,7 @@ If set to a number larger than 0, will debounce the async validation event by th #### Defined in -[packages/form-core/src/FieldApi.ts:188](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L188) +[packages/form-core/src/FieldApi.ts:171](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L171) *** @@ -159,7 +159,7 @@ An optional list of field names that should trigger this field's `onChange` and #### Defined in -[packages/form-core/src/FieldApi.ts:192](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L192) +[packages/form-core/src/FieldApi.ts:175](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L175) *** @@ -173,7 +173,7 @@ An optional function that takes a param of `formApi` which is a generic type of #### Defined in -[packages/form-core/src/FieldApi.ts:150](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L150) +[packages/form-core/src/FieldApi.ts:133](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L133) *** @@ -194,7 +194,7 @@ z.string().min(1) // if `zodAdapter` is passed #### Defined in -[packages/form-core/src/FieldApi.ts:236](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L236) +[packages/form-core/src/FieldApi.ts:219](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L219) *** @@ -215,4 +215,4 @@ z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) // #### Defined in -[packages/form-core/src/FieldApi.ts:249](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L249) +[packages/form-core/src/FieldApi.ts:232](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L232) diff --git a/docs/reference/interfaces/formoptions.md b/docs/reference/interfaces/formoptions.md index c3ba09c51..af7cc1a83 100644 --- a/docs/reference/interfaces/formoptions.md +++ b/docs/reference/interfaces/formoptions.md @@ -25,7 +25,7 @@ If true, always run async validation, even when sync validation has produced an #### Defined in -[packages/form-core/src/FormApi.ts:154](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L154) +[packages/form-core/src/FormApi.ts:163](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L163) *** @@ -39,7 +39,7 @@ Optional time in milliseconds if you want to introduce a delay before firing off #### Defined in -[packages/form-core/src/FormApi.ts:158](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L158) +[packages/form-core/src/FormApi.ts:167](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L167) *** @@ -53,7 +53,7 @@ The default state for the form. #### Defined in -[packages/form-core/src/FormApi.ts:150](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L150) +[packages/form-core/src/FormApi.ts:159](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L159) *** @@ -67,7 +67,7 @@ Set initial values for your form. #### Defined in -[packages/form-core/src/FormApi.ts:146](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L146) +[packages/form-core/src/FormApi.ts:155](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L155) *** @@ -81,11 +81,15 @@ A function to be called when the form is submitted, what should happen once the #### Parameters -• **props** +##### props -• **props.formApi**: [`FormApi`](../classes/formapi.md)\<`TFormData`, `TFormValidator`\> +###### formApi -• **props.value**: `TFormData` +[`FormApi`](../classes/formapi.md)\<`TFormData`, `TFormValidator`\> + +###### value + +`TFormData` #### Returns @@ -93,7 +97,7 @@ A function to be called when the form is submitted, what should happen once the #### Defined in -[packages/form-core/src/FormApi.ts:170](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L170) +[packages/form-core/src/FormApi.ts:179](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L179) *** @@ -107,11 +111,15 @@ Specify an action for scenarios where the user tries to submit an invalid form. #### Parameters -• **props** +##### props + +###### formApi + +[`FormApi`](../classes/formapi.md)\<`TFormData`, `TFormValidator`\> -• **props.formApi**: [`FormApi`](../classes/formapi.md)\<`TFormData`, `TFormValidator`\> +###### value -• **props.value**: `TFormData` +`TFormData` #### Returns @@ -119,7 +127,7 @@ Specify an action for scenarios where the user tries to submit an invalid form. #### Defined in -[packages/form-core/src/FormApi.ts:177](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L177) +[packages/form-core/src/FormApi.ts:186](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L186) *** @@ -131,7 +139,7 @@ optional transform: FormTransform; #### Defined in -[packages/form-core/src/FormApi.ts:181](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L181) +[packages/form-core/src/FormApi.ts:190](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L190) *** @@ -145,7 +153,7 @@ A validator adapter to support usage of extra validation types (IE: Zod, Yup, or #### Defined in -[packages/form-core/src/FormApi.ts:162](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L162) +[packages/form-core/src/FormApi.ts:171](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L171) *** @@ -159,4 +167,4 @@ A list of validators to pass to the form #### Defined in -[packages/form-core/src/FormApi.ts:166](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L166) +[packages/form-core/src/FormApi.ts:175](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L175) diff --git a/docs/reference/interfaces/formvalidators.md b/docs/reference/interfaces/formvalidators.md index 9f750dc52..bd0ad8870 100644 --- a/docs/reference/interfaces/formvalidators.md +++ b/docs/reference/interfaces/formvalidators.md @@ -23,7 +23,7 @@ Optional function that validates the form data when a field loses focus, returns #### Defined in -[packages/form-core/src/FormApi.ts:110](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L110) +[packages/form-core/src/FormApi.ts:119](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L119) *** @@ -37,7 +37,7 @@ Optional onBlur asynchronous validation method for when a field loses focus retu #### Defined in -[packages/form-core/src/FormApi.ts:114](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L114) +[packages/form-core/src/FormApi.ts:123](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L123) *** @@ -51,7 +51,7 @@ The default time in milliseconds that if set to a number larger than 0, will deb #### Defined in -[packages/form-core/src/FormApi.ts:118](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L118) +[packages/form-core/src/FormApi.ts:127](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L127) *** @@ -65,7 +65,7 @@ Optional function that checks the validity of your data whenever a value changes #### Defined in -[packages/form-core/src/FormApi.ts:98](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L98) +[packages/form-core/src/FormApi.ts:107](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L107) *** @@ -79,7 +79,7 @@ Optional onChange asynchronous counterpart to onChange. Useful for more complex #### Defined in -[packages/form-core/src/FormApi.ts:102](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L102) +[packages/form-core/src/FormApi.ts:111](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L111) *** @@ -93,7 +93,7 @@ The default time in milliseconds that if set to a number larger than 0, will deb #### Defined in -[packages/form-core/src/FormApi.ts:106](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L106) +[packages/form-core/src/FormApi.ts:115](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L115) *** @@ -107,7 +107,7 @@ Optional function that fires as soon as the component mounts. #### Defined in -[packages/form-core/src/FormApi.ts:94](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L94) +[packages/form-core/src/FormApi.ts:103](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L103) *** @@ -119,7 +119,7 @@ optional onSubmit: FormValidateOrFn; #### Defined in -[packages/form-core/src/FormApi.ts:119](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L119) +[packages/form-core/src/FormApi.ts:128](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L128) *** @@ -131,4 +131,4 @@ optional onSubmitAsync: FormAsyncValidateOrFn; #### Defined in -[packages/form-core/src/FormApi.ts:120](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L120) +[packages/form-core/src/FormApi.ts:129](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L129) diff --git a/docs/reference/type-aliases/baseformstate.md b/docs/reference/type-aliases/baseformstate.md new file mode 100644 index 000000000..277b5c0e7 --- /dev/null +++ b/docs/reference/type-aliases/baseformstate.md @@ -0,0 +1,94 @@ +--- +id: BaseFormState +title: BaseFormState +--- + +# Type Alias: BaseFormState\ + +```ts +type BaseFormState: object; +``` + +An object representing the current state of the form. + +## Type Parameters + +• **TFormData** + +## Type declaration + +### errorMap + +```ts +errorMap: FormValidationErrorMap; +``` + +The error map for the form itself. + +### fieldMetaBase + +```ts +fieldMetaBase: Record, FieldMetaBase>; +``` + +A record of field metadata for each field in the form, not including the derived properties, like `errors` and such + +### isSubmitted + +```ts +isSubmitted: boolean; +``` + +A boolean indicating if the form has been submitted. + +### isSubmitting + +```ts +isSubmitting: boolean; +``` + +A boolean indicating if the form is currently in the process of being submitted after `handleSubmit` is called. + +Goes back to `false` when submission completes for one of the following reasons: +- the validation step returned errors. +- the `onSubmit` function has completed. + +Note: if you're running async operations in your `onSubmit` function make sure to await them to ensure `isSubmitting` is set to `false` only when the async operation completes. + +This is useful for displaying loading indicators or disabling form inputs during submission. + +### isValidating + +```ts +isValidating: boolean; +``` + +A boolean indicating if the form or any of its fields are currently validating. + +### submissionAttempts + +```ts +submissionAttempts: number; +``` + +A counter for tracking the number of submission attempts. + +### validationMetaMap + +```ts +validationMetaMap: Record; +``` + +An internal mechanism used for keeping track of validation logic in a form. + +### values + +```ts +values: TFormData; +``` + +The current values of the form fields. + +## Defined in + +[packages/form-core/src/FormApi.ts:228](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L228) diff --git a/docs/reference/type-aliases/derivedformstate.md b/docs/reference/type-aliases/derivedformstate.md new file mode 100644 index 000000000..59a7579b7 --- /dev/null +++ b/docs/reference/type-aliases/derivedformstate.md @@ -0,0 +1,116 @@ +--- +id: DerivedFormState +title: DerivedFormState +--- + +# Type Alias: DerivedFormState\ + +```ts +type DerivedFormState: object; +``` + +## Type Parameters + +• **TFormData** + +## Type declaration + +### canSubmit + +```ts +canSubmit: boolean; +``` + +A boolean indicating if the form can be submitted based on its current state. + +### errors + +```ts +errors: ValidationError[]; +``` + +The error array for the form itself. + +### fieldMeta + +```ts +fieldMeta: Record, FieldMeta>; +``` + +A record of field metadata for each field in the form. + +### isBlurred + +```ts +isBlurred: boolean; +``` + +A boolean indicating if any of the form fields have been blurred. + +### isDirty + +```ts +isDirty: boolean; +``` + +A boolean indicating if any of the form's fields' values have been modified by the user. `True` if the user have modified at least one of the fields. Opposite of `isPristine`. + +### isFieldsValid + +```ts +isFieldsValid: boolean; +``` + +A boolean indicating if all the form fields are valid. + +### isFieldsValidating + +```ts +isFieldsValidating: boolean; +``` + +A boolean indicating if any of the form fields are currently validating. + +### isFormValid + +```ts +isFormValid: boolean; +``` + +A boolean indicating if the form is valid. + +### isFormValidating + +```ts +isFormValidating: boolean; +``` + +A boolean indicating if the form is currently validating. + +### isPristine + +```ts +isPristine: boolean; +``` + +A boolean indicating if none of the form's fields' values have been modified by the user. `True` if the user have not modified any of the fields. Opposite of `isDirty`. + +### isTouched + +```ts +isTouched: boolean; +``` + +A boolean indicating if any of the form fields have been touched. + +### isValid + +```ts +isValid: boolean; +``` + +A boolean indicating if the form and all its fields are valid. + +## Defined in + +[packages/form-core/src/FormApi.ts:272](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L272) diff --git a/docs/reference/type-aliases/fieldinfo.md b/docs/reference/type-aliases/fieldinfo.md index 1f11721c6..55b60f198 100644 --- a/docs/reference/type-aliases/fieldinfo.md +++ b/docs/reference/type-aliases/fieldinfo.md @@ -37,4 +37,4 @@ A record of field validation internal handling. ## Defined in -[packages/form-core/src/FormApi.ts:197](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L197) +[packages/form-core/src/FormApi.ts:206](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L206) diff --git a/docs/reference/type-aliases/fieldmeta.md b/docs/reference/type-aliases/fieldmeta.md index 82277a280..2984539a8 100644 --- a/docs/reference/type-aliases/fieldmeta.md +++ b/docs/reference/type-aliases/fieldmeta.md @@ -6,69 +6,11 @@ title: FieldMeta # Type Alias: FieldMeta ```ts -type FieldMeta: object; +type FieldMeta: FieldMetaBase & FieldMetaDerived; ``` An object type representing the metadata of a field in a form. -## Type declaration - -### errorMap - -```ts -errorMap: ValidationErrorMap; -``` - -A map of errors related to the field value. - -### errors - -```ts -errors: ValidationError[]; -``` - -An array of errors related to the field value. - -### isBlurred - -```ts -isBlurred: boolean; -``` - -A flag indicating whether the field has been blurred. - -### isDirty - -```ts -isDirty: boolean; -``` - -A flag that is `true` if the field's value has been modified by the user. Opposite of `isPristine`. - -### isPristine - -```ts -isPristine: boolean; -``` - -A flag that is `true` if the field's value has not been modified by the user. Opposite of `isDirty`. - -### isTouched - -```ts -isTouched: boolean; -``` - -A flag indicating whether the field has been touched. - -### isValidating - -```ts -isValidating: boolean; -``` - -A flag indicating whether the field is currently being validated. - ## Defined in -[packages/form-core/src/FieldApi.ts:334](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L334) +[packages/form-core/src/FieldApi.ts:402](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L402) diff --git a/docs/reference/type-aliases/fieldmetabase.md b/docs/reference/type-aliases/fieldmetabase.md new file mode 100644 index 000000000..763e9fca8 --- /dev/null +++ b/docs/reference/type-aliases/fieldmetabase.md @@ -0,0 +1,56 @@ +--- +id: FieldMetaBase +title: FieldMetaBase +--- + +# Type Alias: FieldMetaBase + +```ts +type FieldMetaBase: object; +``` + +## Type declaration + +### errorMap + +```ts +errorMap: ValidationErrorMap; +``` + +A map of errors related to the field value. + +### isBlurred + +```ts +isBlurred: boolean; +``` + +A flag indicating whether the field has been blurred. + +### isDirty + +```ts +isDirty: boolean; +``` + +A flag that is `true` if the field's value has been modified by the user. Opposite of `isPristine`. + +### isTouched + +```ts +isTouched: boolean; +``` + +A flag indicating whether the field has been touched. + +### isValidating + +```ts +isValidating: boolean; +``` + +A flag indicating whether the field is currently being validated. + +## Defined in + +[packages/form-core/src/FieldApi.ts:365](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L365) diff --git a/docs/reference/type-aliases/fieldmetaderived.md b/docs/reference/type-aliases/fieldmetaderived.md new file mode 100644 index 000000000..54edb3bdb --- /dev/null +++ b/docs/reference/type-aliases/fieldmetaderived.md @@ -0,0 +1,32 @@ +--- +id: FieldMetaDerived +title: FieldMetaDerived +--- + +# Type Alias: FieldMetaDerived + +```ts +type FieldMetaDerived: object; +``` + +## Type declaration + +### errors + +```ts +errors: ValidationError[]; +``` + +An array of errors related to the field value. + +### isPristine + +```ts +isPristine: boolean; +``` + +A flag that is `true` if the field's value has not been modified by the user. Opposite of `isDirty`. + +## Defined in + +[packages/form-core/src/FieldApi.ts:388](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L388) diff --git a/docs/reference/type-aliases/fieldserrormapfromvalidator.md b/docs/reference/type-aliases/fieldserrormapfromvalidator.md index a9416909d..874056b36 100644 --- a/docs/reference/type-aliases/fieldserrormapfromvalidator.md +++ b/docs/reference/type-aliases/fieldserrormapfromvalidator.md @@ -15,4 +15,4 @@ type FieldsErrorMapFromValidator: Partial, ## Defined in -[packages/form-core/src/FormApi.ts:26](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L26) +[packages/form-core/src/FormApi.ts:31](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L31) diff --git a/docs/reference/type-aliases/fieldstate.md b/docs/reference/type-aliases/fieldstate.md index c54a8fb32..3054b5c63 100644 --- a/docs/reference/type-aliases/fieldstate.md +++ b/docs/reference/type-aliases/fieldstate.md @@ -35,4 +35,4 @@ The current value of the field. ## Defined in -[packages/form-core/src/FieldApi.ts:368](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L368) +[packages/form-core/src/FieldApi.ts:407](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L407) diff --git a/docs/reference/type-aliases/formstate.md b/docs/reference/type-aliases/formstate.md index c5c3f1ebb..69f519257 100644 --- a/docs/reference/type-aliases/formstate.md +++ b/docs/reference/type-aliases/formstate.md @@ -6,177 +6,13 @@ title: FormState # Type Alias: FormState\ ```ts -type FormState: object; +type FormState: BaseFormState & DerivedFormState; ``` -An object representing the current state of the form. - ## Type Parameters • **TFormData** -## Type declaration - -### canSubmit - -```ts -canSubmit: boolean; -``` - -A boolean indicating if the form can be submitted based on its current state. - -### errorMap - -```ts -errorMap: FormValidationErrorMap; -``` - -The error map for the form itself. - -### errors - -```ts -errors: ValidationError[]; -``` - -The error array for the form itself. - -### fieldMeta - -```ts -fieldMeta: Record, FieldMeta>; -``` - -A record of field metadata for each field in the form. - -### isBlurred - -```ts -isBlurred: boolean; -``` - -A boolean indicating if any of the form fields have been blurred. - -### isDirty - -```ts -isDirty: boolean; -``` - -A boolean indicating if any of the form's fields' values have been modified by the user. `True` if the user have modified at least one of the fields. Opposite of `isPristine`. - -### isFieldsValid - -```ts -isFieldsValid: boolean; -``` - -A boolean indicating if all the form fields are valid. - -### isFieldsValidating - -```ts -isFieldsValidating: boolean; -``` - -A boolean indicating if any of the form fields are currently validating. - -### isFormValid - -```ts -isFormValid: boolean; -``` - -A boolean indicating if the form is valid. - -### isFormValidating - -```ts -isFormValidating: boolean; -``` - -A boolean indicating if the form is currently validating. - -### isPristine - -```ts -isPristine: boolean; -``` - -A boolean indicating if none of the form's fields' values have been modified by the user. `True` if the user have not modified any of the fields. Opposite of `isDirty`. - -### isSubmitted - -```ts -isSubmitted: boolean; -``` - -A boolean indicating if the form has been submitted. - -### isSubmitting - -```ts -isSubmitting: boolean; -``` - -A boolean indicating if the form is currently in the process of being submitted after `handleSubmit` is called. - -Goes back to `false` when submission completes for one of the following reasons: -- the validation step returned errors. -- the `onSubmit` function has completed. - -Note: if you're running async operations in your `onSubmit` function make sure to await them to ensure `isSubmitting` is set to `false` only when the async operation completes. - -This is useful for displaying loading indicators or disabling form inputs during submission. - -### isTouched - -```ts -isTouched: boolean; -``` - -A boolean indicating if any of the form fields have been touched. - -### isValid - -```ts -isValid: boolean; -``` - -A boolean indicating if the form and all its fields are valid. - -### isValidating - -```ts -isValidating: boolean; -``` - -A boolean indicating if the form or any of its fields are currently validating. - -### submissionAttempts - -```ts -submissionAttempts: number; -``` - -A counter for tracking the number of submission attempts. - -### validationMetaMap - -```ts -validationMetaMap: Record; -``` - -An internal mechanism used for keeping track of validation logic in a form. - -### values - -```ts -values: TFormData; -``` - -The current values of the form fields. - ## Defined in -[packages/form-core/src/FormApi.ts:219](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L219) +[packages/form-core/src/FormApi.ts:323](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L323) diff --git a/docs/reference/type-aliases/formvalidatefn.md b/docs/reference/type-aliases/formvalidatefn.md index 03546e326..097d4837a 100644 --- a/docs/reference/type-aliases/formvalidatefn.md +++ b/docs/reference/type-aliases/formvalidatefn.md @@ -17,11 +17,15 @@ type FormValidateFn: (props) => FormValidationError +#### formApi -• **props.value**: `TFormData` +[`FormApi`](../classes/formapi.md)\<`TFormData`, `TFormValidator`\> + +#### value + +`TFormData` ## Returns @@ -29,4 +33,4 @@ type FormValidateFn: (props) => FormValidationError: object; #### Parameters -• **options** +##### options -• **options.value**: `TType` +###### value -• **fn**: `TFn` +`TType` + +##### fn + +`TFn` #### Returns @@ -37,11 +41,15 @@ type FormValidator: object; #### Parameters -• **options** +##### options + +###### value + +`TType` -• **options.value**: `TType` +##### fn -• **fn**: `TFn` +`TFn` #### Returns @@ -49,4 +57,4 @@ type FormValidator: object; ## Defined in -[packages/form-core/src/FormApi.ts:61](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L61) +[packages/form-core/src/FormApi.ts:68](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L68) diff --git a/docs/reference/type-aliases/standardschemav1.md b/docs/reference/type-aliases/standardschemav1.md new file mode 100644 index 000000000..e97df86f6 --- /dev/null +++ b/docs/reference/type-aliases/standardschemav1.md @@ -0,0 +1,32 @@ +--- +id: StandardSchemaV1 +title: StandardSchemaV1 +--- + +# Type Alias: StandardSchemaV1\ + +```ts +type StandardSchemaV1: object; +``` + +The Standard Schema interface. + +## Type Parameters + +• **Input** = `unknown` + +• **Output** = `Input` + +## Type declaration + +### ~standard + +```ts +readonly ~standard: StandardSchemaV1Props; +``` + +The Standard Schema properties. + +## Defined in + +[packages/form-core/src/standardSchemaValidator.ts:94](https://github.com/TanStack/form/blob/main/packages/form-core/src/standardSchemaValidator.ts#L94) diff --git a/docs/reference/type-aliases/updaterfn.md b/docs/reference/type-aliases/updaterfn.md index b1b0c5a38..0bbd22e59 100644 --- a/docs/reference/type-aliases/updaterfn.md +++ b/docs/reference/type-aliases/updaterfn.md @@ -17,7 +17,9 @@ type UpdaterFn: (input) => TOutput; ## Parameters -• **input**: `TInput` +### input + +`TInput` ## Returns diff --git a/docs/reference/type-aliases/validationmeta.md b/docs/reference/type-aliases/validationmeta.md index d1195bde7..31eb09f9f 100644 --- a/docs/reference/type-aliases/validationmeta.md +++ b/docs/reference/type-aliases/validationmeta.md @@ -23,4 +23,4 @@ An abort controller stored in memory to cancel previous async validation attempt ## Defined in -[packages/form-core/src/FormApi.ts:187](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L187) +[packages/form-core/src/FormApi.ts:196](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L196) diff --git a/docs/typescript.md b/docs/typescript.md index 143ae8c8e..19099ddc1 100644 --- a/docs/typescript.md +++ b/docs/typescript.md @@ -8,7 +8,7 @@ TanStack Form is written 100% in **TypeScript** with the highest quality generic Things to keep in mind: - `strict: true` is required in your `tsconfig.json` to get the most out of TanStack Form's types -- Types currently require using TypeScript v4.8 or greater +- Types currently require using TypeScript v5.1 or greater - Changes to types in this repository are considered **non-breaking** and are usually released as **patch** semver changes (otherwise every type enhancement would be a major version!). - It is **highly recommended that you lock your react-form package version to a specific patch release and upgrade with the expectation that types may be fixed or upgraded between any release** - The non-type-related public API of TanStack Form still follows semver very strictly. diff --git a/examples/angular/array/package.json b/examples/angular/array/package.json index cc6144299..056a00971 100644 --- a/examples/angular/array/package.json +++ b/examples/angular/array/package.json @@ -10,23 +10,23 @@ "test": "ng test" }, "dependencies": { - "@angular/animations": "^17.3.12", - "@angular/common": "^17.3.12", - "@angular/compiler": "^17.3.12", - "@angular/core": "^17.3.12", - "@angular/forms": "^17.3.12", - "@angular/platform-browser": "^17.3.12", - "@angular/platform-browser-dynamic": "^17.3.12", - "@angular/router": "^17.3.12", - "@tanstack/angular-form": "^0.34.0", + "@angular/animations": "^19.0.0", + "@angular/common": "^19.0.0", + "@angular/compiler": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/forms": "^19.0.0", + "@angular/platform-browser": "^19.0.0", + "@angular/platform-browser-dynamic": "^19.0.0", + "@angular/router": "^19.0.0", + "@tanstack/angular-form": "^0.41.0", "rxjs": "^7.8.1", - "tslib": "^2.7.0", + "tslib": "^2.8.1", "zone.js": "^0.15.0" }, "devDependencies": { - "@angular-devkit/build-angular": "^17.3.10", - "@angular/cli": "^17.3.10", - "@angular/compiler-cli": "^17.3.12", - "typescript": "5.4.2" + "@angular-devkit/build-angular": "^19.0.0", + "@angular/cli": "^19.0.0", + "@angular/compiler-cli": "^19.0.0", + "typescript": "5.6.3" } } diff --git a/examples/angular/simple/package.json b/examples/angular/simple/package.json index 6c7232414..64e58f5cb 100644 --- a/examples/angular/simple/package.json +++ b/examples/angular/simple/package.json @@ -10,23 +10,23 @@ "test": "ng test" }, "dependencies": { - "@angular/animations": "^17.3.12", - "@angular/common": "^17.3.12", - "@angular/compiler": "^17.3.12", - "@angular/core": "^17.3.12", - "@angular/forms": "^17.3.12", - "@angular/platform-browser": "^17.3.12", - "@angular/platform-browser-dynamic": "^17.3.12", - "@angular/router": "^17.3.12", - "@tanstack/angular-form": "^0.34.0", + "@angular/animations": "^19.0.0", + "@angular/common": "^19.0.0", + "@angular/compiler": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/forms": "^19.0.0", + "@angular/platform-browser": "^19.0.0", + "@angular/platform-browser-dynamic": "^19.0.0", + "@angular/router": "^19.0.0", + "@tanstack/angular-form": "^0.41.0", "rxjs": "^7.8.1", - "tslib": "^2.7.0", + "tslib": "^2.8.1", "zone.js": "^0.15.0" }, "devDependencies": { - "@angular-devkit/build-angular": "^17.3.10", - "@angular/cli": "^17.3.10", - "@angular/compiler-cli": "^17.3.12", - "typescript": "5.4.2" + "@angular-devkit/build-angular": "^19.0.0", + "@angular/cli": "^19.0.0", + "@angular/compiler-cli": "^19.0.0", + "typescript": "5.6.3" } } diff --git a/examples/angular/valibot/package.json b/examples/angular/valibot/package.json index af546a8ca..a94e83ff0 100644 --- a/examples/angular/valibot/package.json +++ b/examples/angular/valibot/package.json @@ -10,25 +10,25 @@ "test": "ng test" }, "dependencies": { - "@angular/animations": "^17.3.12", - "@angular/common": "^17.3.12", - "@angular/compiler": "^17.3.12", - "@angular/core": "^17.3.12", - "@angular/forms": "^17.3.12", - "@angular/platform-browser": "^17.3.12", - "@angular/platform-browser-dynamic": "^17.3.12", - "@angular/router": "^17.3.12", - "@tanstack/angular-form": "^0.34.0", - "@tanstack/valibot-form-adapter": "^0.34.0", + "@angular/animations": "^19.0.0", + "@angular/common": "^19.0.0", + "@angular/compiler": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/forms": "^19.0.0", + "@angular/platform-browser": "^19.0.0", + "@angular/platform-browser-dynamic": "^19.0.0", + "@angular/router": "^19.0.0", + "@tanstack/angular-form": "^0.41.0", + "@tanstack/valibot-form-adapter": "^0.41.0", "rxjs": "^7.8.1", - "tslib": "^2.7.0", - "valibot": "1.0.0-beta.0", + "tslib": "^2.8.1", + "valibot": "^1.0.0-beta.9", "zone.js": "^0.15.0" }, "devDependencies": { - "@angular-devkit/build-angular": "^17.3.10", - "@angular/cli": "^17.3.10", - "@angular/compiler-cli": "^17.3.12", - "typescript": "5.4.2" + "@angular-devkit/build-angular": "^19.0.0", + "@angular/cli": "^19.0.0", + "@angular/compiler-cli": "^19.0.0", + "typescript": "5.6.3" } } diff --git a/examples/angular/valibot/src/app/app.component.ts b/examples/angular/valibot/src/app/app.component.ts index e5d9fdf15..34e343efa 100644 --- a/examples/angular/valibot/src/app/app.component.ts +++ b/examples/angular/valibot/src/app/app.component.ts @@ -81,7 +81,7 @@ export class AppComponent { // Do something with form data console.log(value) }, - // Add a validator to support Zod usage in Form and Field + // Add a validator to support Zod usage in Form and Field (no longer needed with valibot@1.0.0 or higher) validatorAdapter: valibotValidator(), }) diff --git a/examples/angular/yup/package.json b/examples/angular/yup/package.json index eb888a203..ea9ecec2b 100644 --- a/examples/angular/yup/package.json +++ b/examples/angular/yup/package.json @@ -10,25 +10,25 @@ "test": "ng test" }, "dependencies": { - "@angular/animations": "^17.3.12", - "@angular/common": "^17.3.12", - "@angular/compiler": "^17.3.12", - "@angular/core": "^17.3.12", - "@angular/forms": "^17.3.12", - "@angular/platform-browser": "^17.3.12", - "@angular/platform-browser-dynamic": "^17.3.12", - "@angular/router": "^17.3.12", - "@tanstack/angular-form": "^0.34.0", - "@tanstack/yup-form-adapter": "^0.34.0", + "@angular/animations": "^19.0.0", + "@angular/common": "^19.0.0", + "@angular/compiler": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/forms": "^19.0.0", + "@angular/platform-browser": "^19.0.0", + "@angular/platform-browser-dynamic": "^19.0.0", + "@angular/router": "^19.0.0", + "@tanstack/angular-form": "^0.41.0", + "@tanstack/yup-form-adapter": "^0.41.0", "rxjs": "^7.8.1", - "tslib": "^2.7.0", - "yup": "^1.4.0", + "tslib": "^2.8.1", + "yup": "^1.5.0", "zone.js": "^0.15.0" }, "devDependencies": { - "@angular-devkit/build-angular": "^17.3.10", - "@angular/cli": "^17.3.10", - "@angular/compiler-cli": "^17.3.12", - "typescript": "5.4.2" + "@angular-devkit/build-angular": "^19.0.0", + "@angular/cli": "^19.0.0", + "@angular/compiler-cli": "^19.0.0", + "typescript": "5.6.3" } } diff --git a/examples/angular/zod/package.json b/examples/angular/zod/package.json index ea3272390..255ed6f48 100644 --- a/examples/angular/zod/package.json +++ b/examples/angular/zod/package.json @@ -10,25 +10,25 @@ "test": "ng test" }, "dependencies": { - "@angular/animations": "^17.3.12", - "@angular/common": "^17.3.12", - "@angular/compiler": "^17.3.12", - "@angular/core": "^17.3.12", - "@angular/forms": "^17.3.12", - "@angular/platform-browser": "^17.3.12", - "@angular/platform-browser-dynamic": "^17.3.12", - "@angular/router": "^17.3.12", - "@tanstack/angular-form": "^0.34.0", - "@tanstack/zod-form-adapter": "^0.34.0", + "@angular/animations": "^19.0.0", + "@angular/common": "^19.0.0", + "@angular/compiler": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/forms": "^19.0.0", + "@angular/platform-browser": "^19.0.0", + "@angular/platform-browser-dynamic": "^19.0.0", + "@angular/router": "^19.0.0", + "@tanstack/angular-form": "^0.41.0", + "@tanstack/zod-form-adapter": "^0.41.0", "rxjs": "^7.8.1", - "tslib": "^2.7.0", - "zod": "^3.23.8", + "tslib": "^2.8.1", + "zod": "^3.24.0", "zone.js": "^0.15.0" }, "devDependencies": { - "@angular-devkit/build-angular": "^17.3.10", - "@angular/cli": "^17.3.10", - "@angular/compiler-cli": "^17.3.12", - "typescript": "5.4.2" + "@angular-devkit/build-angular": "^19.0.0", + "@angular/cli": "^19.0.0", + "@angular/compiler-cli": "^19.0.0", + "typescript": "5.6.3" } } diff --git a/examples/angular/zod/src/app/app.component.ts b/examples/angular/zod/src/app/app.component.ts index 2541f657d..4644c892b 100644 --- a/examples/angular/zod/src/app/app.component.ts +++ b/examples/angular/zod/src/app/app.component.ts @@ -80,7 +80,7 @@ export class AppComponent { // Do something with form data console.log(value) }, - // Add a validator to support Zod usage in Form and Field + // Add a validator to support Zod usage in Form and Field (no longer needed with zod@3.24.0 or higher) validatorAdapter: zodValidator(), }) diff --git a/examples/lit/simple/package.json b/examples/lit/simple/package.json index 60db54be7..8230503c6 100644 --- a/examples/lit/simple/package.json +++ b/examples/lit/simple/package.json @@ -9,11 +9,11 @@ "test:types": "tsc" }, "dependencies": { - "@tanstack/lit-form": "^0.34.0", + "@tanstack/lit-form": "^0.41.0", "lit": "^3.2.1" }, "devDependencies": { - "vite": "^5.4.8" + "vite": "^5.4.11" }, "browserslist": { "production": [ diff --git a/examples/lit/ui-libraries/package.json b/examples/lit/ui-libraries/package.json index 6582fefd9..9b0cae2ce 100644 --- a/examples/lit/ui-libraries/package.json +++ b/examples/lit/ui-libraries/package.json @@ -10,11 +10,11 @@ }, "dependencies": { "@material/web": "^2.2.0", - "@tanstack/lit-form": "^0.34.0", + "@tanstack/lit-form": "^0.41.0", "lit": "^3.2.1" }, "devDependencies": { - "vite": "^5.4.8" + "vite": "^5.4.11" }, "browserslist": { "production": [ diff --git a/examples/react/array/package.json b/examples/react/array/package.json index 95390fa67..c281ad21d 100644 --- a/examples/react/array/package.json +++ b/examples/react/array/package.json @@ -9,15 +9,15 @@ "test:types": "tsc" }, "dependencies": { - "@tanstack/react-form": "^0.34.0", + "@tanstack/react-form": "^0.41.0", "react": "^18.3.1", "react-dom": "^18.3.1" }, "devDependencies": { "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@vitejs/plugin-react": "^4.3.2", - "vite": "^5.4.8" + "@vitejs/plugin-react": "^4.3.3", + "vite": "^5.4.11" }, "browserslist": { "production": [ diff --git a/examples/react/compiler/.eslintrc.cjs b/examples/react/compiler/.eslintrc.cjs new file mode 100644 index 000000000..52b3c0f7a --- /dev/null +++ b/examples/react/compiler/.eslintrc.cjs @@ -0,0 +1,16 @@ +// @ts-check +const reactCompiler = require('eslint-plugin-react-compiler') + +/** @type {import('eslint').Linter.Config} */ +const config = { + plugins: { + 'react-compiler': reactCompiler, + }, + extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'], + rules: { + 'react/no-children-prop': 'off', + 'react-compiler/react-compiler': 'error', + }, +} + +module.exports = config diff --git a/examples/react/compiler/.gitignore b/examples/react/compiler/.gitignore new file mode 100644 index 000000000..4673b022e --- /dev/null +++ b/examples/react/compiler/.gitignore @@ -0,0 +1,27 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +pnpm-lock.yaml +yarn.lock +package-lock.json + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/examples/react/compiler/README.md b/examples/react/compiler/README.md new file mode 100644 index 000000000..1cf889265 --- /dev/null +++ b/examples/react/compiler/README.md @@ -0,0 +1,6 @@ +# Example + +To run this example: + +- `npm install` +- `npm run dev` diff --git a/examples/react/compiler/index.html b/examples/react/compiler/index.html new file mode 100644 index 000000000..5d0e76cd4 --- /dev/null +++ b/examples/react/compiler/index.html @@ -0,0 +1,16 @@ + + + + + + + + + TanStack Form React Simple Example App + + + +
+ + + diff --git a/examples/react/compiler/package.json b/examples/react/compiler/package.json new file mode 100644 index 000000000..fa0d2bf5f --- /dev/null +++ b/examples/react/compiler/package.json @@ -0,0 +1,40 @@ +{ + "name": "@tanstack/form-example-react-compiler", + "private": true, + "type": "module", + "scripts": { + "dev": "vite --port=3001", + "build": "vite build", + "preview": "vite preview", + "_test:types": "tsc" + }, + "dependencies": { + "@tanstack/react-form": "^0.41.0", + "react": "^19.0.0-rc.1", + "react-dom": "^19.0.0-rc.1" + }, + "devDependencies": { + "@types/react": "npm:types-react@rc", + "@types/react-dom": "npm:types-react-dom@rc", + "@vitejs/plugin-react": "^4.3.3", + "babel-plugin-react-compiler": "^19.0.0-beta-0dec889-20241115", + "eslint-plugin-react-compiler": "^19.0.0-beta-0dec889-20241115", + "vite": "^5.4.11" + }, + "overrides": { + "@types/react": "npm:types-react@rc", + "@types/react-dom": "npm:types-react-dom@rc" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/examples/react/compiler/public/emblem-light.svg b/examples/react/compiler/public/emblem-light.svg new file mode 100644 index 000000000..a58e69ad5 --- /dev/null +++ b/examples/react/compiler/public/emblem-light.svg @@ -0,0 +1,13 @@ + + + + emblem-light + Created with Sketch. + + + + + + + + \ No newline at end of file diff --git a/examples/react/compiler/src/index.tsx b/examples/react/compiler/src/index.tsx new file mode 100644 index 000000000..67cfca1d3 --- /dev/null +++ b/examples/react/compiler/src/index.tsx @@ -0,0 +1,118 @@ +import { useForm } from '@tanstack/react-form' +import * as React from 'react' +import { createRoot } from 'react-dom/client' +import type { FieldApi } from '@tanstack/react-form' + +function FieldInfo({ field }: { field: FieldApi }) { + return ( + <> + {field.state.meta.isTouched && field.state.meta.errors.length ? ( + {field.state.meta.errors.join(',')} + ) : null} + {field.state.meta.isValidating ? 'Validating...' : null} + + ) +} + +export default function App() { + const form = useForm({ + defaultValues: { + firstName: '', + lastName: '', + }, + onSubmit: async ({ value }) => { + // Do something with form data + console.log(value) + }, + }) + + return ( +
+

Simple Form Example

+
{ + e.preventDefault() + e.stopPropagation() + form.handleSubmit() + }} + > +
+ {/* A type-safe field component*/} + + !value + ? 'A first name is required' + : value.length < 3 + ? 'First name must be at least 3 characters' + : undefined, + onChangeAsyncDebounceMs: 500, + onChangeAsync: async ({ value }) => { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return ( + value.includes('error') && 'No "error" allowed in first name' + ) + }, + }} + children={(field) => { + // Avoid hasty abstractions. Render props are great! + return ( + <> + + field.handleChange(e.target.value)} + /> + + + ) + }} + /> +
+
+ ( + <> + + field.handleChange(e.target.value)} + /> + + + )} + /> +
+ [state.canSubmit, state.isSubmitting]} + children={([canSubmit, isSubmitting]) => ( + <> + + + + )} + /> + +
+ ) +} + +const rootElement = document.getElementById('root')! + +createRoot(rootElement).render( + + + , +) diff --git a/examples/react/compiler/tsconfig.json b/examples/react/compiler/tsconfig.json new file mode 100644 index 000000000..22b43163b --- /dev/null +++ b/examples/react/compiler/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ESNext", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/examples/react/compiler/vite.config.ts b/examples/react/compiler/vite.config.ts new file mode 100644 index 000000000..a152a8424 --- /dev/null +++ b/examples/react/compiler/vite.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +const ReactCompilerConfig = {} + +export default defineConfig(() => { + return { + plugins: [ + react({ + babel: { + plugins: [['babel-plugin-react-compiler', ReactCompilerConfig]], + }, + }), + ], + } +}) diff --git a/examples/react/field-errors-from-form-validators/package.json b/examples/react/field-errors-from-form-validators/package.json index b7c92204f..87cee67c4 100644 --- a/examples/react/field-errors-from-form-validators/package.json +++ b/examples/react/field-errors-from-form-validators/package.json @@ -9,15 +9,15 @@ "test:types": "tsc" }, "dependencies": { - "@tanstack/react-form": "^0.34.0", + "@tanstack/react-form": "^0.41.0", "react": "^18.3.1", "react-dom": "^18.3.1" }, "devDependencies": { "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@vitejs/plugin-react": "^4.3.2", - "vite": "^5.4.8" + "@vitejs/plugin-react": "^4.3.3", + "vite": "^5.4.11" }, "browserslist": { "production": [ diff --git a/examples/react/next-server-actions/next.config.cjs b/examples/react/next-server-actions/next.config.mjs similarity index 76% rename from examples/react/next-server-actions/next.config.cjs rename to examples/react/next-server-actions/next.config.mjs index a843cbee0..94be31c3d 100644 --- a/examples/react/next-server-actions/next.config.cjs +++ b/examples/react/next-server-actions/next.config.mjs @@ -3,4 +3,4 @@ const nextConfig = { reactStrictMode: true, } -module.exports = nextConfig +export default nextConfig diff --git a/examples/react/next-server-actions/package.json b/examples/react/next-server-actions/package.json index 6b3624be9..72fa3dd8c 100644 --- a/examples/react/next-server-actions/package.json +++ b/examples/react/next-server-actions/package.json @@ -8,16 +8,17 @@ "_test:types": "tsc" }, "dependencies": { - "@tanstack/react-form": "^0.34.0", - "next": "15.0.0-rc.0", - "react": "19.0.0-rc-5dcb0097-20240918", - "react-dom": "19.0.0-rc-5dcb0097-20240918" + "@tanstack/react-form": "^0.41.0", + "@tanstack/react-store": "^0.7.0", + "next": "15.0.3", + "react": "^19.0.0", + "react-dom": "^19.0.0" }, "devDependencies": { - "@types/node": "^20.14.10", + "@types/node": "^22.10.1", "@types/react": "npm:types-react@rc", "@types/react-dom": "npm:types-react-dom@rc", - "typescript": "5.4.2" + "typescript": "5.6.3" }, "overrides": { "@types/react": "npm:types-react@rc", diff --git a/examples/react/next-server-actions/src/app/client-component.tsx b/examples/react/next-server-actions/src/app/client-component.tsx index 2f754b49a..8942b7477 100644 --- a/examples/react/next-server-actions/src/app/client-component.tsx +++ b/examples/react/next-server-actions/src/app/client-component.tsx @@ -3,6 +3,7 @@ import { useActionState } from 'react' import { mergeForm, useForm, useTransform } from '@tanstack/react-form' import { initialFormState } from '@tanstack/react-form/nextjs' +import { useStore } from '@tanstack/react-store' import someAction from './action' import { formOpts } from './shared-code' @@ -17,7 +18,7 @@ export const ClientComp = () => { ), }) - const formErrors = form.useStore((formState) => formState.errors) + const formErrors = useStore(form.store, (formState) => formState.errors) return (
form.handleSubmit()}> diff --git a/examples/react/query-integration/package.json b/examples/react/query-integration/package.json index dd5e9eb57..01bbee576 100644 --- a/examples/react/query-integration/package.json +++ b/examples/react/query-integration/package.json @@ -9,16 +9,16 @@ "test:types": "tsc" }, "dependencies": { - "@tanstack/react-form": "^0.34.0", - "@tanstack/react-query": "^5.59.13", + "@tanstack/react-form": "^0.41.0", + "@tanstack/react-query": "^5.59.20", "react": "^18.3.1", "react-dom": "^18.3.1" }, "devDependencies": { "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@vitejs/plugin-react": "^4.3.2", - "vite": "^5.4.8" + "@vitejs/plugin-react": "^4.3.3", + "vite": "^5.4.11" }, "browserslist": { "production": [ diff --git a/examples/react/remix/.gitignore b/examples/react/remix/.gitignore new file mode 100644 index 000000000..80ec311f4 --- /dev/null +++ b/examples/react/remix/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/.cache +/build +.env diff --git a/examples/react/remix/README.md b/examples/react/remix/README.md new file mode 100644 index 000000000..6c4d2168f --- /dev/null +++ b/examples/react/remix/README.md @@ -0,0 +1,40 @@ +# Welcome to Remix! + +- 📖 [Remix docs](https://remix.run/docs) + +## Development + +Run the dev server: + +```shellscript +npm run dev +``` + +## Deployment + +First, build your app for production: + +```sh +npm run build +``` + +Then run the app in production mode: + +```sh +npm start +``` + +Now you'll need to pick a host to deploy it to. + +### DIY + +If you're familiar with deploying Node applications, the built-in Remix app server is production-ready. + +Make sure to deploy the output of `npm run build` + +- `build/server` +- `build/client` + +## Styling + +This template comes with [Tailwind CSS](https://tailwindcss.com/) already configured for a simple default starting experience. You can use whatever css framework you prefer. See the [Vite docs on css](https://vitejs.dev/guide/features.html#css) for more information. diff --git a/examples/react/remix/app/root.tsx b/examples/react/remix/app/root.tsx new file mode 100644 index 000000000..dfc07954d --- /dev/null +++ b/examples/react/remix/app/root.tsx @@ -0,0 +1,29 @@ +import { + Links, + Meta, + Outlet, + Scripts, + ScrollRestoration, +} from '@remix-run/react' + +export function Layout({ children }: { children: React.ReactNode }) { + return ( + + + + + + + + + {children} + + + + + ) +} + +export default function App() { + return +} diff --git a/examples/react/remix/app/routes/_index/route.tsx b/examples/react/remix/app/routes/_index/route.tsx new file mode 100644 index 000000000..e8f25e194 --- /dev/null +++ b/examples/react/remix/app/routes/_index/route.tsx @@ -0,0 +1,99 @@ +import { Form, useActionData } from '@remix-run/react' + +import { mergeForm, useForm, useTransform } from '@tanstack/react-form' +import { + ServerValidateError, + createServerValidate, + formOptions, + initialFormState, +} from '@tanstack/react-form/remix' +import { useStore } from '@tanstack/react-store' + +import type { ActionFunctionArgs } from '@remix-run/node' + +const formOpts = formOptions({ + defaultValues: { + firstName: '', + age: 0, + }, +}) + +const serverValidate = createServerValidate({ + ...formOpts, + onServerValidate: ({ value }) => { + if (value.age < 12) { + return 'Server validation: You must be at least 12 to sign up' + } + }, +}) + +export async function action({ request }: ActionFunctionArgs) { + const formData = await request.formData() + try { + await serverValidate(formData) + } catch (e) { + if (e instanceof ServerValidateError) { + return e.formState + } + + // Some other error occurred while validating your form + throw e + } + + // Your form has successfully validated! + return null +} + +export default function Index() { + const actionData = useActionData() + + const form = useForm({ + ...formOpts, + transform: useTransform( + (baseForm) => mergeForm(baseForm, actionData ?? {}), + [actionData], + ), + }) + const formErrors = useStore(form.store, (formState) => formState.errors) + + return ( + form.handleSubmit()}> + {formErrors.map((error) => ( +

{error}

+ ))} + + + value < 8 ? 'Client validation: You must be at least 8' : undefined, + }} + > + {(field) => { + return ( +
+ field.handleChange(e.target.valueAsNumber)} + /> + {field.state.meta.errors.map((error) => ( +

{error}

+ ))} +
+ ) + }} +
+ [formState.canSubmit, formState.isSubmitting]} + > + {([canSubmit, isSubmitting]) => ( + + )} + + + ) +} diff --git a/examples/react/remix/package.json b/examples/react/remix/package.json new file mode 100644 index 000000000..3d01b99ff --- /dev/null +++ b/examples/react/remix/package.json @@ -0,0 +1,31 @@ +{ + "name": "@tanstack/form-example-remix", + "private": true, + "type": "module", + "scripts": { + "build": "remix vite:build", + "dev": "remix vite:dev", + "_test:types": "tsc" + }, + "dependencies": { + "@remix-run/node": "^2.15.0", + "@remix-run/react": "^2.15.0", + "@remix-run/serve": "^2.15.0", + "@tanstack/react-form": "^0.41.0", + "@tanstack/react-store": "^0.7.0", + "isbot": "^5.1.17", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@remix-run/dev": "^2.15.0", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "typescript": "5.6.3", + "vite": "^5.4.11", + "vite-tsconfig-paths": "^5.1.2" + }, + "engines": { + "node": ">=20.0.0" + } +} diff --git a/examples/react/remix/public/favicon.ico b/examples/react/remix/public/favicon.ico new file mode 100644 index 000000000..8830cf682 Binary files /dev/null and b/examples/react/remix/public/favicon.ico differ diff --git a/examples/react/remix/tsconfig.json b/examples/react/remix/tsconfig.json new file mode 100644 index 000000000..9d87dd378 --- /dev/null +++ b/examples/react/remix/tsconfig.json @@ -0,0 +1,32 @@ +{ + "include": [ + "**/*.ts", + "**/*.tsx", + "**/.server/**/*.ts", + "**/.server/**/*.tsx", + "**/.client/**/*.ts", + "**/.client/**/*.tsx" + ], + "compilerOptions": { + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "types": ["@remix-run/node", "vite/client"], + "isolatedModules": true, + "esModuleInterop": true, + "jsx": "react-jsx", + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "target": "ES2022", + "strict": true, + "allowJs": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "paths": { + "~/*": ["./app/*"] + }, + + // Vite takes care of building everything, not tsc. + "noEmit": true + } +} diff --git a/examples/react/remix/vite.config.ts b/examples/react/remix/vite.config.ts new file mode 100644 index 000000000..4c1144115 --- /dev/null +++ b/examples/react/remix/vite.config.ts @@ -0,0 +1,16 @@ +import { vitePlugin as remix } from '@remix-run/dev' +import { defineConfig } from 'vite' +import tsconfigPaths from 'vite-tsconfig-paths' + +export default defineConfig({ + plugins: [ + remix({ + future: { + v3_fetcherPersist: true, + v3_relativeSplatPath: true, + v3_throwAbortReason: true, + }, + }), + tsconfigPaths(), + ], +}) diff --git a/examples/react/simple/package.json b/examples/react/simple/package.json index 8bfc38f44..3b3668c9f 100644 --- a/examples/react/simple/package.json +++ b/examples/react/simple/package.json @@ -9,15 +9,15 @@ "test:types": "tsc" }, "dependencies": { - "@tanstack/react-form": "^0.34.0", + "@tanstack/react-form": "^0.41.0", "react": "^18.3.1", "react-dom": "^18.3.1" }, "devDependencies": { "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@vitejs/plugin-react": "^4.3.2", - "vite": "^5.4.8" + "@vitejs/plugin-react": "^4.3.3", + "vite": "^5.4.11" }, "browserslist": { "production": [ diff --git a/examples/react/standard-schema/.eslintrc.cjs b/examples/react/standard-schema/.eslintrc.cjs new file mode 100644 index 000000000..35853b617 --- /dev/null +++ b/examples/react/standard-schema/.eslintrc.cjs @@ -0,0 +1,11 @@ +// @ts-check + +/** @type {import('eslint').Linter.Config} */ +const config = { + extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'], + rules: { + 'react/no-children-prop': 'off', + }, +} + +module.exports = config diff --git a/examples/react/standard-schema/.gitignore b/examples/react/standard-schema/.gitignore new file mode 100644 index 000000000..4673b022e --- /dev/null +++ b/examples/react/standard-schema/.gitignore @@ -0,0 +1,27 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +pnpm-lock.yaml +yarn.lock +package-lock.json + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/examples/react/standard-schema/README.md b/examples/react/standard-schema/README.md new file mode 100644 index 000000000..1cf889265 --- /dev/null +++ b/examples/react/standard-schema/README.md @@ -0,0 +1,6 @@ +# Example + +To run this example: + +- `npm install` +- `npm run dev` diff --git a/examples/react/standard-schema/index.html b/examples/react/standard-schema/index.html new file mode 100644 index 000000000..ae98ae4a2 --- /dev/null +++ b/examples/react/standard-schema/index.html @@ -0,0 +1,16 @@ + + + + + + + + + TanStack Form React Standard Schema Example App + + + +
+ + + diff --git a/examples/react/standard-schema/package.json b/examples/react/standard-schema/package.json new file mode 100644 index 000000000..b2d3afff7 --- /dev/null +++ b/examples/react/standard-schema/package.json @@ -0,0 +1,37 @@ +{ + "name": "@tanstack/form-example-react-standard-schema", + "private": true, + "type": "module", + "scripts": { + "dev": "vite --port=3001", + "build": "vite build", + "preview": "vite preview", + "test:types": "tsc" + }, + "dependencies": { + "@tanstack/react-form": "^0.41.0", + "arktype": "2.0.0-rc.23", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "valibot": "^1.0.0-beta.9", + "zod": "^3.24.0" + }, + "devDependencies": { + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.3", + "vite": "^5.4.11" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/examples/react/standard-schema/public/emblem-light.svg b/examples/react/standard-schema/public/emblem-light.svg new file mode 100644 index 000000000..a58e69ad5 --- /dev/null +++ b/examples/react/standard-schema/public/emblem-light.svg @@ -0,0 +1,13 @@ + + + + emblem-light + Created with Sketch. + + + + + + + + \ No newline at end of file diff --git a/examples/react/standard-schema/src/index.tsx b/examples/react/standard-schema/src/index.tsx new file mode 100644 index 000000000..6e463526f --- /dev/null +++ b/examples/react/standard-schema/src/index.tsx @@ -0,0 +1,135 @@ +import { useForm } from '@tanstack/react-form' +import { type } from 'arktype' +import * as React from 'react' +import { createRoot } from 'react-dom/client' +import * as v from 'valibot' +import { z } from 'zod' +import type { FieldApi } from '@tanstack/react-form' + +function FieldInfo({ field }: { field: FieldApi }) { + return ( + <> + {field.state.meta.isTouched && field.state.meta.errors.length ? ( + {field.state.meta.errors.join(',')} + ) : null} + {field.state.meta.isValidating ? 'Validating...' : null} + + ) +} + +const ZodSchema = z.object({ + firstName: z + .string() + .min(3, '[Zod] You must have a length of at least 3') + .startsWith('A', "[Zod] First name must start with 'A'"), + lastName: z.string().min(3, '[Zod] You must have a length of at least 3'), +}) + +const ValibotSchema = v.object({ + firstName: v.pipe( + v.string(), + v.minLength(3, '[Valibot] You must have a length of at least 3'), + v.startsWith('A', "[Valibot] First name must start with 'A'"), + ), + lastName: v.pipe( + v.string(), + v.minLength(3, '[Valibot] You must have a length of at least 3'), + ), +}) + +const ArkTypeSchema = type({ + firstName: 'string >= 3', + lastName: 'string >= 3', +}) + +export default function App() { + const form = useForm({ + defaultValues: { + firstName: '', + lastName: '', + }, + validators: { + // DEMO: You can switch between schemas seamlessly + onChange: ZodSchema, + // onChange: ValibotSchema, + // onChange: ArkTypeSchema, + }, + onSubmit: async ({ value }) => { + // Do something with form data + console.log(value) + }, + // DEMO: There's no need to pass an adapter! You may use it only if you need to pass custom options. + // validatorAdapter: standardSchemaValidator(), + // validatorAdapter: standardSchemaValidator({ transformErrors: (issues) => issues.map((issue) => issue.message)[0] }), + }) + + return ( +
+

Standard Schema Form Example

+
{ + e.preventDefault() + e.stopPropagation() + form.handleSubmit() + }} + > +
+ {/* A type-safe field component*/} + { + // Avoid hasty abstractions. Render props are great! + return ( + <> + + field.handleChange(e.target.value)} + /> + + + ) + }} + /> +
+
+ ( + <> + + field.handleChange(e.target.value)} + /> + + + )} + /> +
+ [state.canSubmit, state.isSubmitting]} + children={([canSubmit, isSubmitting]) => ( + + )} + /> + +
+ ) +} + +const rootElement = document.getElementById('root')! + +createRoot(rootElement).render( + + + , +) diff --git a/examples/react/standard-schema/tsconfig.json b/examples/react/standard-schema/tsconfig.json new file mode 100644 index 000000000..f8f7ffb72 --- /dev/null +++ b/examples/react/standard-schema/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ESNext", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": false, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/examples/react/tanstack-start/app/routes/index.tsx b/examples/react/tanstack-start/app/routes/index.tsx index 9cd4329cf..0b8e8bb87 100644 --- a/examples/react/tanstack-start/app/routes/index.tsx +++ b/examples/react/tanstack-start/app/routes/index.tsx @@ -1,5 +1,6 @@ import { createFileRoute } from '@tanstack/react-router' import { mergeForm, useForm, useTransform } from '@tanstack/react-form' +import { useStore } from '@tanstack/react-store' import { formOpts, getFormDataFromServer, handleForm } from '~/utils/form' export const Route = createFileRoute('/')({ @@ -16,7 +17,7 @@ function Home() { transform: useTransform((baseForm) => mergeForm(baseForm, state), [state]), }) - const formErrors = form.useStore((formState) => formState.errors) + const formErrors = useStore(form.store, (formState) => formState.errors) return (
diff --git a/examples/react/tanstack-start/package.json b/examples/react/tanstack-start/package.json index 2642d6efe..a767b8dcf 100644 --- a/examples/react/tanstack-start/package.json +++ b/examples/react/tanstack-start/package.json @@ -9,21 +9,22 @@ "start": "vinxi start" }, "dependencies": { - "@tanstack/form-core": "^0.34.0", - "@tanstack/react-form": "^0.34.0", - "@tanstack/react-router": "^1.65.0", - "@tanstack/start": "^1.66.0", + "@tanstack/form-core": "^0.41.0", + "@tanstack/react-form": "^0.41.0", + "@tanstack/react-router": "^1.81.1", + "@tanstack/react-store": "^0.7.0", + "@tanstack/start": "^1.81.1", "react": "^18.3.1", "react-dom": "^18.3.1", "vinxi": "^0.4.3" }, "devDependencies": { - "@types/node": "^20.14.10", + "@types/node": "^22.10.1", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@vitejs/plugin-react": "^4.3.2", - "typescript": "5.4.2", - "vite": "^5.4.8", - "vite-tsconfig-paths": "^5.0.1" + "@vitejs/plugin-react": "^4.3.3", + "typescript": "5.6.3", + "vite": "^5.4.11", + "vite-tsconfig-paths": "^5.1.2" } } diff --git a/examples/react/ui-libraries/package.json b/examples/react/ui-libraries/package.json index c81d40096..0c8a9d7d1 100644 --- a/examples/react/ui-libraries/package.json +++ b/examples/react/ui-libraries/package.json @@ -11,12 +11,12 @@ "dependencies": { "@emotion/react": "11.13.3", "@emotion/styled": "11.13.0", - "@mantine/core": "7.13.2", - "@mantine/hooks": "7.13.2", + "@mantine/core": "7.13.5", + "@mantine/hooks": "7.13.5", "@mui/material": "5.16.7", - "@tanstack/react-form": "^0.34.0", + "@tanstack/react-form": "^0.41.0", "@yme/lay-postcss": "0.1.0", - "postcss": "8.4.47", + "postcss": "8.4.48", "postcss-preset-mantine": "1.17.0", "postcss-simple-vars": "7.0.1", "react": "^18.3.1", @@ -25,10 +25,10 @@ "devDependencies": { "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@vitejs/plugin-react": "^4.3.2", + "@vitejs/plugin-react": "^4.3.3", "@vitejs/plugin-react-swc": "^3.7.1", - "typescript": "5.4.2", - "vite": "^5.4.8" + "typescript": "5.6.3", + "vite": "^5.4.11" }, "browserslist": { "production": [ diff --git a/examples/react/ui-libraries/src/MainComponent.tsx b/examples/react/ui-libraries/src/MainComponent.tsx index 8229e0d01..04792a234 100644 --- a/examples/react/ui-libraries/src/MainComponent.tsx +++ b/examples/react/ui-libraries/src/MainComponent.tsx @@ -1,12 +1,12 @@ import '@mantine/core/styles.css' -import { MantineProvider, TextInput, Checkbox } from '@mantine/core' +import { Checkbox, MantineProvider, TextInput } from '@mantine/core' import { useForm } from '@tanstack/react-form' import TextField from '@mui/material/TextField' import { Checkbox as MuiCheckbox } from '@mui/material' export default function MainComponent() { - const { Field, Subscribe, handleSubmit, state, useStore } = useForm({ + const form = useForm({ defaultValues: { firstName: '', lastName: '', @@ -18,19 +18,17 @@ export default function MainComponent() { console.log(value) }, }) - console.log({ - values: useStore((state) => state.values), - }) + return ( { e.preventDefault() e.stopPropagation() - handleSubmit() + form.handleSubmit() }} > - { return ( @@ -43,7 +41,7 @@ export default function MainComponent() { ) }} /> - { return ( @@ -59,7 +57,7 @@ export default function MainComponent() { ) }} /> - { return ( @@ -71,7 +69,7 @@ export default function MainComponent() { ) }} /> - { return ( @@ -83,7 +81,7 @@ export default function MainComponent() { ) }} /> - [state.canSubmit, state.isSubmitting]} children={([canSubmit, isSubmitting]) => (