Installation Install the Form component by running the following command:
npx shadcn-ui@latest add form Install Emblor by running the following command:
npm install emblor
# Or, use any package manager of your choice. Create a form schema Define the shape of your form using a Zod schema. You can read more about using Zod in the Zod documentation .
'use client' ;
import { z } from 'zod' ;
const FormSchema = z. object ({
topics: z. array (
z. object ({
id: z. string (),
text: z. string (),
}),
),
}); Define a form Use the useForm hook from react-hook-form to create a form.
'use client' ;
import { zodResolver } from '@hookform/resolvers/zod' ;
import { useForm } from 'react-hook-form' ;
import { z } from 'zod' ;
const FormSchema = z. object ({
topics: z. array (
z. object ({
id: z. string (),
text: z. string (),
}),
),
});
export function Form () {
// 1. Define your form.
const form = useForm < z . infer < typeof FormSchema>>({
resolver: zodResolver (FormSchema),
defaultValues: {
topics: [],
},
});
// 2. Define a submit handler.
function onSubmit ( data : z . infer < typeof FormSchema>) {
toast ({
title: 'You submitted the following values:' ,
description : (
< pre className = "mt-2 w-[340px] rounded-md bg-slate-950 p-4" >
< code className = "text-white" >{ JSON . stringify (data, null , 2 )}</ code >
</ pre >
),
});
}
} Since FormField is using a controlled component, you need to provide a default value for the field. See the React Hook Form docs to learn more about controlled components.
Build your form We can now use the Form components to build our form.
'use client' ;
import { zodResolver } from '@hookform/resolvers/zod' ;
import { useForm } from 'react-hook-form' ;
import { z } from 'zod' ;
import { Button } from '@/components/ui/button' ;
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form' ;
import { Tag, TagInput } from 'emblor' ;
const FormSchema = z. object ({
topics: z. array (
z. object ({
id: z. string (),
text: z. string (),
}),
),
});
export function Form () {
// ...
const [ tags , setTags ] = React. useState < Tag []>([]);
const { setValue } = form;
return (
< Form { ... form}>
< form onSubmit = {form. handleSubmit (onSubmit)} className = "space-y-8 flex flex-col items-start" >
< FormField
control = {form.control}
name = "topics"
render = {({ field }) => (
< FormItem className = "flex flex-col items-start" >
< FormLabel className = "text-left" >Topics</ FormLabel >
< FormControl className = "w-full" >
< TagInput
{ ... field}
placeholder = "Enter a topic"
tags = {tags}
className = "sm:min-w-[450px]"
setTags = {( newTags ) => {
setTags (newTags);
setValue ( 'topics' , newTags as [ Tag , ... Tag []]);
}}
/>
</ FormControl >
< FormDescription className = "text-left" >
These are the topics that you ' re interested in.
</ FormDescription >
< FormMessage />
</ FormItem >
)}
/>
< Button type = "submit" >Submit</ Button >
</ form >
</ Form >
);
} Done That's it. You now have a fully accessible form that is type-safe with client-side validation.