Schema
/ GuidesSchema
/ GuidesGenerating Forms
One powerful use case for JSON schemas is generating forms.
For this guide, we'll use React, but you it basically works the same in any view library.
Let's imagine we have the following Zod schema:
import { z } from 'zod'
const schema = z.object({
name: z.string(),
age: z.number(),
email: z.string().email(),
})
Rendering Inputs
We can now use fromZod together with our guards to render inputs based on the schema:
import { ComponentProps } from 'react'
import { fromZod } from '@weser/schema'
const json = fromZod(schema)
const fields = Object.entries(json.properties)
function Form() {
return (
<form>
{fields.map(([name, field]) => {
if (isNumberSchema(field)) {
return <Input name={name} label={name} type="number" />
}
return (
<Input
name={name}
label={name}
type={field.format === 'email' ? 'email' : 'text'}
/>
)
})}
</form>
)
}
function Input({ name, label, type }: ComponentProps<'input'>) {
return (
<label htmlFor={name}>
<span>{label}</span>
<input name={name} id={name} type={type} />
</label>
)
}
Using @weser/forms
Going a step further, we can use @weser/forms to manage the form state and validation.
import { ZodError } from 'zod'
import { ComponentProps } from 'react'
import { fromZod } from '@weser/schema'
import { useForm } from '@weser/forms'
type T_Schema = z.infer<typeof schema>
const json = fromZod(schema)
const fields = Object.entries(json.properties)
function Form() {
const { useFormField, handleSubmit, reset } = useForm(schema)
function onSuccess(data: T_Schema) {
// do something with the data
console.log(data)
reset()
}
function onFailure(error: ZodError) {
console.error(error)
}
return (
<form onSubmit={handleSubmit(onSuccess, onFailure)}>
{fields.map(([name, field]) => {
const field = useFormField(name)
if (isNumberSchema(field)) {
return <Input label={name} type="number" {...field.inputProps} />
}
return (
<Input
label={name}
type={field.format === 'email' ? 'email' : 'text'}
{...field.inputProps}
/>
)
})}
</form>
)
}
© 2024-present Robin Weser. All Rights Reserved.