Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: native support for standard schema libraries #1020

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5604751
feat: naive implementation as adapter
Balastrong Nov 15, 2024
f0bdd57
test: naive test with valibot
Balastrong Nov 15, 2024
b4e5652
feat: add async validation support
Balastrong Nov 16, 2024
b1d61f6
feat: define standard schema adapter in form-core
Balastrong Nov 16, 2024
74e9b6f
feat: support arktype's function-based structure and path
Balastrong Nov 16, 2024
1983e75
ci: apply automated fixes and generate docs
autofix-ci[bot] Nov 16, 2024
0c5f51a
feat: validate form with standard schema without adapter
Balastrong Nov 16, 2024
ac20225
feat: validate field with standard schema without adapter
Balastrong Nov 16, 2024
c67628d
test: add todo tests for zod
Balastrong Nov 16, 2024
c8a3ec4
ci: apply automated fixes and generate docs
autofix-ci[bot] Nov 16, 2024
aec622b
fix: spread field errors from form validator
Balastrong Nov 16, 2024
ddac46f
docs: add example with multiple schemas
Balastrong Nov 16, 2024
4d88afc
Merge branch 'main' into feat/standard-schema-implementation
Balastrong Nov 16, 2024
0ffa635
chore: bump valibot and uncomment failing tests
Balastrong Nov 18, 2024
f6e677b
docs: mention standard schema
Balastrong Nov 18, 2024
3c3b1a5
Merge branch 'main' into feat/standard-schema-implementation
Balastrong Nov 19, 2024
d1128c1
feat: accept functional sync validator even with an adapter set
Balastrong Nov 19, 2024
bc585e7
chore: bump versions
Balastrong Nov 19, 2024
e711d11
Merge branch 'main' into feat/standard-schema-implementation
Balastrong Dec 10, 2024
61a3f1e
docs: gen
Balastrong Dec 10, 2024
5bd7931
ci: apply automated fixes and generate docs
autofix-ci[bot] Dec 10, 2024
22e63f4
feat: integrate zod
Balastrong Dec 10, 2024
ff783ae
docs: update with zod and simplify examples
Balastrong Dec 10, 2024
738b880
ci: apply automated fixes and generate docs
autofix-ci[bot] Dec 10, 2024
b5ed17a
docs: mention latest version for schema libraries
Balastrong Dec 10, 2024
3ef2ab0
Merge branch 'feat/standard-schema-implementation' of https://github.…
Balastrong Dec 10, 2024
336368d
chore: bump valibot
Balastrong Dec 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,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"
Expand Down
88 changes: 49 additions & 39 deletions docs/framework/angular/guides/validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -420,19 +418,18 @@ import { z } from 'zod'
`,
})
export class AppComponent {
form = injectForm({
// Either add the validator here or on `Field`
validatorAdapter: zodValidator(),
form = injectForm({
// ...
})
})

z = z

// ...
}
```

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({
Expand Down Expand Up @@ -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: `
<ng-container
[tanstackField]="form"
name="age"
[validators]="{
onChange: yup.number().moreThan(13, 'You must be 13 to make an account'),
}"
#age="field"
>
<!-- ... -->
</ng-container>
`,
})
export class AppComponent {
form = injectForm({
// Either add the validator here or on `Field`
validatorAdapter: yupValidator(),
// ...
})

This means that:
yup = yup

```html
<ng-container [tanstackField]="form" name="age" #age="field">
<!-- ... -->
</ng-container>
// ...
}
```

Will still display the error message from the form-level validation.

## Preventing invalid forms from being submitted

Expand Down
6 changes: 3 additions & 3 deletions docs/framework/react/guides/ssr.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -315,7 +315,7 @@ Here, we're using [React's `useActionState` hook](https://unicorn-utterances.com

- 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#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]

## Remix integration

Expand Down
102 changes: 50 additions & 52 deletions docs/framework/react/guides/validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
})

<form.Field
name="age"
validatorAdapter={zodValidator()}
validators={{
onChange: z.number().gte(13, 'You must be 13 to make an account'),
}}
children={(field) => {
return <>{/* ... */}</>
}}
/>
function App() {
const form = useForm({
defaultValues: {
age: 0,
},
validators: {
onChange: userSchema,
},
})
return (
<div>
<form.Field
name="age"
children={(field) => {
return <>{/* ... */}</>
}}
/>
</div>
)
}
```

These adapters also support async operations using the proper property names:
Async validations on form and field level are supported as well:

```tsx
<form.Field
Expand All @@ -477,44 +479,40 @@ These adapters also support async operations using the proper property names:
/>
```

### 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

<form.Field
name="age"
validatorAdapter={yupValidator()}
validators={{
onChange: yup.number().moreThan(13, 'You must be 13 to make an account'),
}}
children={(field) => {
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.
Expand Down
Loading
Loading