Skip to content

Commit 6b00ad4

Browse files
committed
docs: added valibot examples
1 parent e36556d commit 6b00ad4

File tree

6 files changed

+177
-17
lines changed

6 files changed

+177
-17
lines changed

docs/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"shiki": "^0.14.3",
3131
"tailwindcss": "^3.3.3",
3232
"unist-util-visit": "^5.0.0",
33+
"valibot": "^0.7.0",
3334
"vee-validate": "^4.11.0",
3435
"vue": "^3.3.0",
3536
"yup": "^1.2.0",

docs/src/components/Repl.vue

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const files = await Promise.all(
2020
const code = await import(`./examples/${componentName}.vue?raw`);
2121
2222
return [filename, code.default];
23-
})
23+
}),
2424
);
2525
2626
const store = new ReplStore({
@@ -33,13 +33,15 @@ store.setImportMap({
3333
'vee-validate': 'https://unpkg.com/vee-validate@latest/dist/vee-validate.esm.js',
3434
'@vee-validate/zod': 'https://unpkg.com/@vee-validate/zod@latest/dist/vee-validate-zod.esm.js',
3535
'@vee-validate/yup': 'https://unpkg.com/@vee-validate/yup@latest/dist/vee-validate-yup.esm.js',
36+
'@vee-validate/valibot': 'https://unpkg.com/@vee-validate/valibot@latest/dist/vee-validate-valibot.esm.js',
3637
'@vee-validate/i18n': 'https://unpkg.com/@vee-validate/i18n@latest/dist/vee-validate-i18n.esm.js',
3738
'@vee-validate/rules': 'https://unpkg.com/@vee-validate/rules@latest/dist/vee-validate-rules.esm.js',
3839
'property-expr': 'https://esm-repo.netlify.app/property-expr.esm.js',
3940
'tiny-case': 'https://esm-repo.netlify.app/tiny-case.esm.js',
4041
toposort: 'https://esm-repo.netlify.app/topsort.esm.js',
4142
yup: 'https://unpkg.com/[email protected]/index.esm.js',
4243
zod: 'https://unpkg.com/[email protected]/lib/index.mjs',
44+
valibot: 'https://unpkg.com/browse/[email protected]/dist/index.js',
4345
'@vue/devtools-api': 'https://unpkg.com/@vue/[email protected]/lib/esm/index.js',
4446
vue: `https://unpkg.com/vue@${version}/dist/vue.esm-browser.prod.js`,
4547
},
@@ -49,11 +51,14 @@ store.setImportMap({
4951
store.setVueVersion(version);
5052
5153
function onForkClick() {
52-
const exampleFiles = files.reduce((acc, file) => {
53-
acc[file[0]] = file[1];
54-
55-
return acc;
56-
}, {} as Record<string, string>);
54+
const exampleFiles = files.reduce(
55+
(acc, file) => {
56+
acc[file[0]] = file[1];
57+
58+
return acc;
59+
},
60+
{} as Record<string, string>,
61+
);
5762
5863
StackBlitzSdk.openProject(getViteProjectConfig(exampleFiles), {
5964
newWindow: true,
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<script setup>
2+
import { useForm } from 'vee-validate';
3+
import { toTypedSchema } from '@vee-validate/valibot';
4+
import { email, string, minLength, object } from 'valibot';
5+
6+
const { errors, defineInputBinds } = useForm({
7+
validationSchema: toTypedSchema(
8+
object({
9+
email: string([minLength(1, 'Email is required'), email()]),
10+
password: string([minLength(6, 'password too short')]),
11+
}),
12+
),
13+
});
14+
15+
const emailField = defineInputBinds('email');
16+
const passwordField = defineInputBinds('password');
17+
</script>
18+
19+
<template>
20+
<input v-bind="emailField" />
21+
<div>{{ errors.email }}</div>
22+
23+
<input v-bind="passwordField" />
24+
<div>{{ errors.password }}</div>
25+
</template>

docs/src/pages/guide/composition-api/getting-started.mdx

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,13 +280,51 @@ There is a known issue with Zod's `refine` and `superRefine` not executing whene
280280

281281
</DocTip>
282282

283-
### Validating with global validators
283+
### Validating with Valibot
284+
285+
You can also use [Valibot](https://valibot.dev/) which is is a schema library with bundle size, type safety and developer experience in mind. It is a great alternative to Yup and Zod if bundle size is a concern. You will need to use the `@vee-validate/valibot` package to use valibot schemas.
286+
287+
```sh
288+
# with npm
289+
npm i @vee-validate/valibot
290+
# with pnpm
291+
pnpm add @vee-validate/valibot
292+
# with yarn
293+
yarn add @vee-validate/valibot
294+
```
295+
296+
Then you can wrap your Valibot schemas with `toTypedSchema` function which allows vee-validate to infer form input and output types. [More on that here](/guide/composition-api/typed-schema).
297+
298+
```ts
299+
import { useForm } from 'vee-validate';
300+
import { string, object, email, minLength } from 'valibot';
301+
import { toTypedSchema } from '@vee-validate/valibot';
302+
303+
// Creates a typed schema for vee-validate
304+
const schema = toTypedSchema(
305+
object({
306+
email: string([minLength(1, 'required'), email()]),
307+
}),
308+
);
309+
310+
const { errors, values } = useForm({
311+
validationSchema: schema,
312+
});
313+
```
314+
315+
Here is a full example using valibot with `useForm`:
316+
317+
<Repl files={{ 'App.vue': 'CompositionValibotBasic' }} client:only />
318+
319+
### Other validation providers and options
320+
321+
#### Global Rules
284322

285323
Another option is using `@vee-validate/rules` which have been historically bundled with past versions of vee-validate. It includes rules that can be defined globally and then used anywhere using Laravel-like string expressions.
286324

287325
You can refer to the full guide on global rules [here](/guide/global-validators).
288326

289-
### Validating with functions
327+
#### Validating with functions
290328

291329
Another option is to just use any 3rd party validation tool you prefer, something like [`validator.js`](https://github.com/validatorjs/validator.js/). Here is a quick example:
292330

docs/src/pages/guide/composition-api/typed-schema.mdx

Lines changed: 97 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ next:
1212
---
1313

1414
import DocTip from '@/components/DocTip.vue';
15-
import DocBadge from '@/components/DocBadge.vue';
1615

17-
# Typed Schemas <DocBadge title="v4.8" />
16+
# Typed Schemas
1817

1918
<DocTip type="warn">
2019

@@ -114,7 +113,7 @@ const { values, handleSubmit } = useForm({
114113
email: string().required(),
115114
password: string().required(),
116115
name: string(),
117-
})
116+
}),
118117
),
119118
});
120119

@@ -146,7 +145,7 @@ const { values, handleSubmit } = useForm({
146145
email: string().required().default('[email protected]'),
147146
password: string().required().default(''),
148147
name: string().default(''),
149-
})
148+
}),
150149
),
151150
});
152151
```
@@ -168,12 +167,12 @@ const { values, handleSubmit } = useForm({
168167
age: number()
169168
.transform(val => Number(val))
170169
.required(),
171-
})
170+
}),
172171
),
173172
});
174173
```
175174

176-
But note that this does not change the input or output types of the casted fields. The cast will only occur when setting the initial value and when the values are submitted.
175+
But note that this does not change the input or output types of the casted fields. The cast will only occur when setting the initial value and when the values are submitted in the submission handler.
177176

178177
## Zod
179178

@@ -209,7 +208,7 @@ const { values, handleSubmit } = useForm({
209208
email: string().min(1, 'required'),
210209
password: string().min(1, 'required'),
211210
name: string().optional(),
212-
})
211+
}),
213212
),
214213
});
215214

@@ -246,7 +245,7 @@ const { values, handleSubmit } = useForm({
246245
object({
247246
email: string().default('[email protected]'),
248247
password: string().default(''),
249-
})
248+
}),
250249
),
251250
});
252251
```
@@ -266,7 +265,7 @@ const { values, handleSubmit } = useForm({
266265
validationSchema: toTypedSchema(
267266
object({
268267
age: preprocess(val => Number(val), number()),
269-
})
268+
}),
270269
),
271270
});
272271

@@ -278,3 +277,92 @@ handleSubmit(submitted => {
278277
values.age;
279278
});
280279
```
280+
281+
## Valibot
282+
283+
[Valibot](https://valibot.dev/) is a schema library with bundle size, type safety and developer experience in mind. It is a great alternative to Yup and Zod if bundle size is a concern.
284+
285+
You can use valibot as a typed schema with the `@vee-validate/valibot` package:
286+
287+
```sh
288+
# npm
289+
npm install @vee-validate/valibot
290+
# yarn
291+
yarn add @vee-validate/valibot
292+
# pnpm
293+
pnpm add @vee-validate/valibot
294+
```
295+
296+
The `@vee-valdiate/valibot` package exposes a `toTypedSchema` function that accepts any valibot schema. Which then you can pass along to `validationSchema` option on `useForm`.
297+
298+
This makes the form values and submitted values typed automatically and caters for both input and output types of that schema.
299+
300+
```ts
301+
import { useForm } from 'vee-validate';
302+
import { object, string, minLength } from 'valibot';
303+
import { toTypedSchema } from '@vee-validate/valibot';
304+
305+
const { values, handleSubmit } = useForm({
306+
validationSchema: toTypedSchema(
307+
object({
308+
email: string([minLength(1, 'required')]),
309+
password: string([minLength(1, 'required')]),
310+
name: string(),
311+
}),
312+
),
313+
});
314+
315+
// ❌ Type error, which means `values` is type-safe
316+
values.email.endsWith('@gmail.com');
317+
318+
handleSubmit(submitted => {
319+
// No errors, because email is required!
320+
submitted.email.endsWith('@gmail.com');
321+
322+
// ❌ Type error, because `name` is not required so it could be undefined
323+
// Means that your fields are now type safe!
324+
submitted.name.length;
325+
});
326+
```
327+
328+
### Valibot default values
329+
330+
You can also define default values on your schema directly and it will be picked up by the form:
331+
332+
```ts
333+
import { useForm } from 'vee-validate';
334+
import { object, string, useDefault, minLength } from 'valibot';
335+
import { toTypedSchema } from '@vee-validate/valibot';
336+
337+
const { values, handleSubmit } = useForm({
338+
validationSchema: toTypedSchema(
339+
object({
340+
email: useDefault(string([minLength(1, 'required')]), '[email protected]'),
341+
password: useDefault(string([minLength(1, 'required')]), ''),
342+
name: useDefault(string(), ''),
343+
}),
344+
),
345+
});
346+
```
347+
348+
Your initial values will be using the schema defaults, and also the defaults will be used if the values submitted is missing these fields.
349+
350+
### Valibot transforms
351+
352+
You can also define transforms to cast your fields before submission:
353+
354+
```ts
355+
import { useForm } from 'vee-validate';
356+
import { object, number, coerce, any } from 'valibot';
357+
import { toTypedSchema } from '@vee-validate/valibot';
358+
359+
const { values, handleSubmit } = useForm({
360+
validationSchema: toTypedSchema(
361+
object({
362+
age: coerce(any(), arg => Number(arg)),
363+
}),
364+
),
365+
});
366+
```
367+
368+
But note that this does not change the input or output types of the casted fields. The cast will only occur when setting the initial value and when the values are submitted in the submission handler.

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)