🛠️ VitNode is still in development! You can try it out, but it is not recommended to use it now in production.
🖌️ Themes
Forms

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)
});