Forms
Forms are a common part of web applications. They allow users to input data and submit it to the server. In VitNode, we use the react-hook-form (opens in a new tab) library to handle forms. This library is lightweight and easy to use. It also integrates well with the zod
library for form validation.
Usage
Create a Hook
We're recomend to create a hook to handle the form state and submission. It will make your code cleaner and easier to maintain.
Create a new file in frontend/admin/blog/views/categories/create-edit/hooks/use-create-edit-category-blog-admin.ts
and add the following code:
export const useCreateEditCategoryBlogAdmin = () => {};
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 (opens in a new tab).
import * as z from "zod";
import { zodInput } from "@/functions/zod";
export const useCreateEditCategoryBlogAdmin = () => {
const formSchema = z.object({
name: zodInput.languageInput.min(1),
description: zodInput.languageInput
});
};
We used the zodInput
helper to create a custom validation function. You can read more about it in the Custom validation zod section.
Define a form
Define the form state with default values with return the form
object.
import * as z from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { zodInput } from "@/functions/zod";
export const useCreateEditCategoryBlogAdmin = () => {
const formSchema = z.object({
name: zodInput.languageInput.min(1),
description: zodInput.languageInput
});
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
name: [],
description: []
}
});
return { form };
};
Define a submit handler
Define the submit handler that will be called when the form is submitted and return the onSubmit
function.
import * as z from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { zodInput } from "@/functions/zod";
export const useCreateEditCategoryBlogAdmin = () => {
const formSchema = z.object({
name: zodInput.languageInput.min(1),
description: zodInput.languageInput
});
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
name: [],
description: []
}
});
const onSubmit = (values: z.infer<typeof formSchema>) => {
// Do something
};
return { form, onSubmit };
};
In onSubmit
function you can call Mutation with Server Action.
Build your form
We can now use the <Form />
components to build our form.
import { useTranslations } from "next-intl";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage
} from "@/components/ui/form";
import { useCreateEditCategoryBlogAdmin } from "./hooks/use-create-edit-category-blog-admin";
import { TextLanguageInput } from "@/components/text-language-input";
import { Button } from "@/components/ui/button";
import { Editor } from "@/components/editor/editor";
interface Props {
data?: unknown;
}
export const CreateEditCategoryBlogAdmin = ({ data }: Props) => {
const t = useTranslations("blog.admin.categories");
const { form, onSubmit } = useCreateEditCategoryBlogAdmin();
return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="flex flex-col gap-4"
>
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>{t("create.name.label")}</FormLabel>
<FormControl>
<TextLanguageInput {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormItem>
<FormLabel>{t("create.description.label")}</FormLabel>
<FormControl>
<Editor {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
onClick={form.handleSubmit(onSubmit)}
loading={form.formState.isSubmitting}
disabled={!form.formState.isValid}
>
{t(data ? "edit.submit" : "create.submit")}
</Button>
</form>
</Form>
);
};
Upload Files
This feature is currently planned but not yet implemented.
Custom validation zod
VitNode provides a custom validation function that allows you to use the zod
schema to validate the form data.
Text Language Input
This validation trims the input and create an array of objects with the language code and the value.
import { zodInput } from "@/functions/zod";
const formSchema = z.object({
name: zodInput.languageInput
});
You can make the input required by adding the .min(1)
method.
import { zodInput } from "@/functions/zod";
const formSchema = z.object({
name: zodInput.languageInput.min(1)
});
String
This validation trims the input. We're recomend to use this validation insted of z.string()
.
import { zodInput } from "@/functions/zod";
const formSchema = z.object({
name: zodInput.string
});
You can make the input required by adding the .min(1)
method.
import { zodInput } from "@/functions/zod";
const formSchema = z.object({
name: zodInput.string.min(1)
});