52 | );
53 | }
54 |
--------------------------------------------------------------------------------
/docs/components/pages/Home/index.tsx:
--------------------------------------------------------------------------------
1 | import Highlights from "./Highlights";
2 | import HeroContent from "./HeroContent";
3 | import Features from "./Feature";
4 | import { HomeDemo } from "../../HomeDemo";
5 |
6 | export default function HomeContent() {
7 | return (
8 | <>
9 |
10 |
11 |
12 |
13 | >
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/docs/custom.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --shiki-color-text: #414141;
3 | --shiki-color-background: transparent;
4 | --shiki-token-constant: #1976d2;
5 | --shiki-token-string: #CCFFF7;
6 | --shiki-token-comment: #aaa;
7 | --shiki-token-keyword: #d32f2f;
8 | --shiki-token-parameter: #ff9800;
9 | --shiki-token-function: #6f42c1;
10 | --shiki-token-string-expression: #CCFFF7;
11 | --shiki-token-punctuation: #212121;
12 | --shiki-token-link: #CCFFF7;
13 | }
14 |
15 | .dark {
16 | --shiki-color-text: #d1d1d1;
17 | --shiki-token-constant: #79b8ff;
18 | --shiki-token-string: #ffab70;
19 | --shiki-token-comment: #6b737c;
20 | --shiki-token-keyword: #f97583;
21 | --shiki-token-parameter: #ff9800;
22 | --shiki-token-function: #b392f0;
23 | --shiki-token-string-expression: #CCFFF7;
24 | --shiki-token-punctuation: #bbb;
25 | --shiki-token-link: #ffab70;
26 | }
--------------------------------------------------------------------------------
/docs/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 | @tailwind variants;
5 |
6 | /* Override the Tailwind preflight */
7 | button[type="submit"] {
8 | @apply bg-black;
9 | }
10 |
11 | @layer utilities {
12 | /* Hide scrollbar for Chrome, Safari and Opera */
13 | .no-scrollbar::-webkit-scrollbar {
14 | display: none;
15 | }
16 |
17 | /* Hide scrollbar for Edge and Firefox */
18 | .no-scrollbar {
19 | -ms-overflow-style: none; /* Edge */
20 | scrollbar-width: none; /* Firefox */
21 | }
22 |
23 | @keyframes slidein {
24 | from {
25 | transform: translate3d(0, 0, 0);
26 | }
27 |
28 | to {
29 | transform: translate3d(-100%, 0, 0);
30 | }
31 | }
32 |
33 | .wrapper {
34 | position: relative;
35 | white-space: nowrap;
36 | display: inline-block;
37 | animation: slidein 120s linear infinite;
38 | filter: grayscale(100%);
39 | }
40 | }
41 |
42 | /* Override Nextra defaults */
43 | article.nextra-body-typesetting-article {
44 | line-height: 1.75;
45 | }
46 | article.nextra-body-typesetting-article p {
47 | line-height: 1.75 !important;
48 | }
49 |
50 | article.nextra-body-typesetting-article h1,
51 | article.nextra-body-typesetting-article h2,
52 | article.nextra-body-typesetting-article h3,
53 | article.nextra-body-typesetting-article h4 {
54 | line-height: 1.25 !important;
55 | }
--------------------------------------------------------------------------------
/docs/index.d.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-explicit-any */
2 | declare module "*.svg" {
3 | const content: any;
4 | export const ReactComponent: any;
5 | export default content;
6 | }
7 |
--------------------------------------------------------------------------------
/docs/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/docs/next-sitemap.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next-sitemap').IConfig} */
2 | module.exports = {
3 | siteUrl: 'https://useform.org',
4 | generateRobotsTxt: true,
5 | sitemapSize: 7000,
6 | sourceDir: '.next',
7 | };
8 |
--------------------------------------------------------------------------------
/docs/next.config.js:
--------------------------------------------------------------------------------
1 | const withNextra = require("nextra")({
2 | theme: "nextra-theme-docs",
3 | themeConfig: "./theme.config.tsx",
4 | });
5 |
6 | module.exports = withNextra();
7 |
--------------------------------------------------------------------------------
/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@createform/docs",
3 | "version": "4.0.7",
4 | "description": "Createform docs",
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "postbuild": "next-sitemap",
9 | "start": "next start"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/jucian0/createform.git"
14 | },
15 | "author": "Jucian0 ",
16 | "license": "MIT",
17 | "bugs": {
18 | "url": "https://github.com/jucian0/createform/issues"
19 | },
20 | "homepage": "https://useform.org",
21 | "dependencies": {
22 | "@next/env": "13.3.0",
23 | "@createform/react": "workspace:*",
24 | "@heroicons/react": "v1",
25 | "@react-aria/ssr": "3.4.1",
26 | "@vercel/analytics": "0.1.8",
27 | "classnames": "2.3.2",
28 | "next": "14.2.10",
29 | "nextra": "2.3.0",
30 | "nextra-theme-docs": "2.3.0",
31 | "swr": "2.0.3",
32 | "tailwindcss": "3.2.6",
33 | "framer-motion": "9.0.2",
34 | "next-sitemap": "4.0.6",
35 | "react": "18.2.0",
36 | "react-dom": "18.2.0",
37 | "clsx": "1.2.1",
38 | "zod": "3.22.3",
39 | "react-select": "5.7.2",
40 | "react-datepicker": "4.11.0"
41 | },
42 | "devDependencies": {
43 | "@types/node": "18.11.10",
44 | "autoprefixer": "^10.4.13",
45 | "postcss": "^8.4.31",
46 | "typescript": "^4.9.3",
47 | "@createform/tsconfig": "workspace:*"
48 | }
49 | }
--------------------------------------------------------------------------------
/docs/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import "../globals.css";
2 | import "../custom.css";
3 |
4 | import { SSRProvider } from "@react-aria/ssr";
5 | import type { AppProps } from "next/app";
6 | import type { ReactNode } from "react";
7 | import { Analytics } from "@vercel/analytics/react";
8 |
9 | type NextraAppProps = AppProps & {
10 | Component: AppProps["Component"] & {
11 | getLayout: (page: ReactNode) => ReactNode;
12 | };
13 | };
14 |
15 | // Shim requestIdleCallback in Safari
16 | if (typeof window !== "undefined" && !("requestIdleCallback" in window)) {
17 | (window as any).requestIdleCallback = (fn) => setTimeout(fn, 1);
18 | (window as any).cancelIdleCallback = (e) => clearTimeout(e);
19 | }
20 |
21 | export default function Nextra({ Component, pageProps }: NextraAppProps) {
22 | return (
23 |
24 |
25 |
26 |
27 | );
28 | }
29 |
--------------------------------------------------------------------------------
/docs/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | import Document, { Html, Head, Main, NextScript } from "next/document";
2 | import type { DocumentInitialProps, DocumentContext } from "next/document";
3 |
4 | class MyDocument extends Document {
5 | static async getInitialProps(
6 | ctx: DocumentContext
7 | ): Promise {
8 | const initialProps = await Document.getInitialProps(ctx);
9 |
10 | return initialProps;
11 | }
12 |
13 | render() {
14 | return (
15 |
16 |
17 |
18 |
23 |
27 |
28 | {/* eslint-disable-next-line @next/next/google-font-preconnect */}
29 |
36 | {/* eslint-disable-next-line @next/next/google-font-preconnect */}
37 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | );
51 | }
52 | }
53 |
54 | export default MyDocument;
55 |
--------------------------------------------------------------------------------
/docs/pages/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": {
3 | "title": "Home",
4 | "type": "page",
5 | "display": "hidden",
6 | "theme": {
7 | "layout": "raw"
8 | }
9 | },
10 | "quick-start": "Quick start",
11 | "api-reference": "API Reference",
12 | "createform": "createForm()",
13 | "useform": "useForm()",
14 | "tutorials": "Tutorials",
15 | "docs": {
16 | "title": "Docs",
17 | "type": "page",
18 | "href": "/quick-start"
19 | },
20 | "about": {
21 | "title": "About",
22 | "display": "hidden"
23 | }
24 | }
--------------------------------------------------------------------------------
/docs/pages/about.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: About
3 | description: CreateForm is an open-source JavaScript library for building user-friendly and responsive forms.
4 | tags: react, form, useform, createform, use-form, hook
5 | ---
6 |
7 | # About CreateForm Library
8 |
9 | CreateForm is an open-source JavaScript library for building user-friendly and responsive forms. With a simple and intuitive API, CreateForm makes it easy to create complex forms with dynamic elements and validation in just a few lines of code.
10 |
11 | ## Features:
12 |
13 | - Easy integration: CreateForm can be easily integrated with any modern JavaScript framework or no-framework project.
14 | - Dynamic form elements: CreateForm makes it easy to add, remove, or update form elements dynamically.
15 | - Validation: CreateForm supports a wide range of validation rules, including custom validation functions, to ensure that the form data is accurate and reliable.
16 | - Responsive design: CreateForm forms are fully responsive, adapting to the screen size and orientation of the user's device.
17 | - Cross-browser compatibility: CreateForm is compatible with all modern browsers, including Chrome, Firefox, Safari, and Edge.
18 |
19 | ## Getting Started:
20 |
21 | To get started with CreateForm, simply install the library using npm or yarn, and import it into your project. Then, use the CreateForm API to build your form, adding form elements, validation rules, and custom styles as needed.
22 |
23 | ## Documentation:
24 |
25 | Full documentation and usage examples are available on the CreateForm website, along with a community forum for support and discussion.
26 |
27 | ## Conclusion:
28 |
29 | Whether you're building a simple contact form or a complex data entry application, CreateForm has the features and flexibility you need to get the job done. So why wait? Start building your forms with CreateForm today!
30 |
--------------------------------------------------------------------------------
/docs/pages/api-reference/use-form.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: useForm
3 | description: This guide describes all steps to create a form using useForm
4 | tags: react, form, useform, createform, use-form, debounce, debounced, hook, yup, validation, form-error, error
5 | ---
6 |
7 | import Callout from "../../components/Callout";
8 |
9 | # useForm
10 |
11 | `useForm` is hook that allow you to create a form in a more natively way, it means that `useForm` uses native events and web standarts to manage and create a form.
12 |
13 | ## useForm params
14 |
15 | ### initialValues
16 |
17 | The initial values of the `createForm` function depend on the initial values of the form fields that you want to manage with the hook. For example, if you want to manage a form with three fields - name, email, and password - the initial values of the `useForm` hook would look something like this:
18 |
19 | ```js copy
20 | import { useForm } from "@createform/react";
21 |
22 | const form = useForm({
23 | initialValues: {
24 | name: "",
25 | email: "",
26 | password: "",
27 | },
28 | });
29 | ```
30 |
31 | Now, form state will contain the initial values for each of the form fields that you are managing with the `useForm`.
32 |
33 |
34 |
35 | It's important to note that the initial values of the `useForm` function are not required - you can initialize the hook without specifying any initial values. But, we recommend to add initialValues.
36 |
37 |
38 |
39 | ### initialErrors
40 |
41 | This property represents a errors object that has all properties of a form values.
42 |
43 | ```jsx copy
44 | import { useForm } from "@createform/react";
45 |
46 | const yourHookForm = useForm({
47 | initialErrors: {
48 | name: "Invalid name!",
49 | email: "Invalid format!",
50 | accept: "This field is required!",
51 | },
52 | });
53 | ```
54 |
55 | ## useForm return object
56 |
57 | `useForm` return an object with some properties, we are going to cover them in the next section:
58 |
59 | - **`register()`** - Different from `createForm` hook, `register` function from `useForm` should be used just in the `` element, this function provides all handlers, and properties to manage the form.
60 |
61 | ```jsx
62 | export function FormDataWay() {
63 | const { register } = useForm({});
64 | return (
65 |
68 | );
69 | }
70 | ```
71 |
72 | - **`setFieldValue()`** - This function is typically used in the context of a form. It allows you to set the value of a specific field in the form. This can be useful for pre-populating form fields with default values, or for programmatically setting the value of a field based on the user's input in other fields. For example, if you have a form with a field for the user's first and last name, example: `setFieldError("name","Jesse")`.
73 |
74 | - **`setFieldsValue()`** - function is similar to the setFieldValue function, but it allows you to set the values of multiple fields in a form at once. This can be useful for pre-populating a form with default values, or for programmatically setting the values of multiple fields based on the user's input in other fields. For example, if you have a form with fields for the user's first and last name, you could use setFieldsValue to set the values of both fields at the same time. This would ensure that the form always contains the most up-to-date values based on the user's input.
75 |
76 | ```jsx copy
77 | const { setFieldValues } = useForm();
78 |
79 | setFieldsValue({
80 | name: "Jesse",
81 | lastName: "...",
82 | });
83 |
84 | //or
85 |
86 | setFieldsValue((state) => ({
87 | ...state,
88 | lastName: "...",
89 | }));
90 | ```
91 |
92 | - **`setFieldError()`** - This function is typically used in a form validation context. It allows you to set an error message for a specific field in a form. This is useful for providing feedback to the user about what went wrong with their input. For example, if a user enters an invalid email address, you could use setFieldError to set the error message for the email field to something like `setFieldError("email","Please enter a valid email address.")` This error message would then be displayed to the user so that they know what they need to fix in order to successfully submit the form.
93 |
94 | - **`setFieldsError()`** - This function is similar to the setFieldError function, but it allows you to set error messages for multiple fields in a form at once. This can be useful for providing feedback to the user about any errors in their input. For example, if a user submits a form with multiple invalid fields, you could use setFieldsError to set the error messages for all of the invalid fields at the same time. This would allow the user to easily see all of the errors in their input and correct them before resubmitting the form.
95 |
96 | ```jsx copy
97 | const { setFieldsError } = yourHookForm();
98 |
99 | setFieldsError({
100 | name: "Invalid name!",
101 | lastName: "This field is required!",
102 | });
103 |
104 | //or
105 |
106 | setFieldsError((state) => ({
107 | ...state,
108 | lastName: "This field is required!",
109 | }));
110 | ```
111 |
112 | - **`getValues()`** - This function is used to get the values of all fields in a form.
113 | - **`getErrors()`** - This function is used to get the errors of all fields in a form.
114 | - **`errors`** - This is an object that contains the errors of all fields in a form.
115 |
--------------------------------------------------------------------------------
/docs/pages/createform/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "how-it-works": "How it works",
3 | "creating-forms": "Creating forms",
4 | "validation": "Validation",
5 | "using-your-form": "Using your form",
6 | "async-data": "Async Data",
7 | "form-submission": "Form submission",
8 | "testing": "Testing"
9 | }
--------------------------------------------------------------------------------
/docs/pages/createform/async-data.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Async Data/Editing Form
3 | description: This tutorial doc guide contains the concept of `loadData`, and how to use it.
4 | tags: react, form, useform, createform, hook, loadData
5 | ---
6 |
7 | import Callout from "../../components/Callout";
8 |
9 | # Concepts
10 |
11 | HTML forms can be used to save or update values. When updating, it's necessary to fetch the data from the server and update the client-side form state. With the loadData function, we can fetch the data from the server and update the form state.
12 |
13 | ## Loading data from server
14 |
15 | When editing a form, we load the form data from the server asynchronously. The best way to do that is by using the loadData function. This function can receive parameters. The following example shows how to load data from the server and update the form state.
16 |
17 |
18 | For TypeScript users, it's necessary to type the form. This can be done by using the `CreateForm` type definition.
19 |
20 |
21 | ```tsx
22 | type Form = CreateForm<
23 | {
24 | email: string;
25 | password: string;
26 | options: string;
27 | },
28 | string
29 | >;
30 | ```
31 |
32 | ### Example
33 |
34 | ```jsx
35 | import { createForm } from "@createform/react";
36 |
37 | const form = createForm({
38 | initialValues: {
39 | name: "",
40 | email: "",
41 | phone: "",
42 | },
43 | loadData: async (id) => {
44 | return await fetch(
45 | `https://jsonplaceholder.typicode.com/users/${id}`)
46 | }
47 | })
48 |
49 | const FormExample = () => {
50 |
51 | const { register, handleSubmit, formState } = form();
52 |
53 | return (...)
54 | }
55 | ```
56 |
57 |
58 | ## Reloading data from server
59 |
60 | Usually, when updating data, the application should be redirected to another page. However, in specific cases, you can reload the data to display the new data by using the reloadData function.
61 | ```jsx
62 | import { createForm } from "@createform/react";
63 |
64 | const form = createForm({
65 | initialValues: {
66 | name: "",
67 | email: "",
68 | phone: "",
69 | },
70 | loadData: async (id) => {
71 | return await fetch(
72 | `https://jsonplaceholder.typicode.com/users/${id}`)
73 | },
74 | })
75 |
76 | const FormExample = () => {
77 | cont {reloadData} = form();
78 | }
79 | ```
80 |
81 |
82 | You can also use `setFieldsValue`, but we recommend using `loadData` instead.
83 |
84 |
--------------------------------------------------------------------------------
/docs/pages/createform/creating-forms/debounced-form.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Debounced mode
3 | description: When you use debounced form, the debounce parameter delays the updating of the state until the user has stopped changing inputs for a predetermined amount of time.
4 | tags: react, form, useform,createform, use-form, debounce, debounced, hook, reactjs
5 | ---
6 |
7 | import Callout from "../../../components/Callout";
8 | import Demo from "../../../components/Demo";
9 | import { FormDemo } from "../../../components/DebouncedDemo";
10 | import { Tab, Tabs } from "../../../components/Tabs";
11 |
12 | # Debounced mode
13 |
14 |
15 |
16 |
17 |
18 |
19 | ```jsx
20 | import { createForm } from "@createform/react";
21 | import { z } from "zod";
22 |
23 | const useForm = createForm({
24 | initialValues: {
25 | email: "",
26 | password: "",
27 | terms: false,
28 | },
29 | mode: "debounced",
30 | validationSchema: z.object({
31 | email: z.string().email(),
32 | password: z.string().min(8),
33 | terms: z.boolean(),
34 | }),
35 | });
36 |
37 | function FormDemo() {
38 | const { register, state } = useForm();
39 | const {errors, touched} = state
40 |
41 | function handleSubmit(data){console.log(data)}
42 |
43 | return (
44 |
97 | )
98 | }
99 | ```
100 |
101 |
102 |
103 | ## Introduction
104 |
105 | Debounce function forces a function to wait a certain amount of time before running again. The function is built to limit the number of times a function is called.
106 |
107 | The debounce parameter delays the updating of the state until the user has stopped changing inputs for a predetermined amount of time.
108 |
109 | The input value is set to state values and then updated via React events. Defining a form’s input value via state is considered a controlled component. For controlled inputs, you will need a corresponding state and then a function to update that state with changes.
110 |
111 | [React Docs](https://reactjs.org/docs/forms.html)
112 |
113 | It means that whenever state is changed the component, it is rendered again.
114 |
115 | If you want to use this kind of form, you need only pass property `mode:'debounced'`.
116 |
117 | Also, it means that the validations are run in every state change, providing better user feedback.
118 | See more in Controlled Inputs with validation.
119 |
120 | ## Usage
121 |
122 | Createform provides a `register` function, this function returns all properties to manager a field.
123 |
124 | ```jsx copy
125 | import { createForm } from "@createform/react";
126 |
127 | const useForm = createForm({
128 | initialValues: {
129 | name: "Anna",
130 | address: [
131 | {
132 | street: "123 Main St",
133 | city: "Anytown",
134 | },
135 | ],
136 | },
137 | mode: "debounced",
138 | });
139 | ```
140 |
141 | Use dot notation to create advanced objects or to map object values. Type an entry name and type or an entry property object.
142 |
143 |
144 |
145 | - Dot notation is used to access nested objects. For example, if you have an object with a nested object, you can access the nested object using dot notation; `info.name`.
146 | - Use dot notation to access nested arrays. For example, if you have an object with a nested array, you can access the nested array using dot notation; `info.array[2]`.
147 |
148 |
149 |
150 | ```jsx copy
151 | function Form() {
152 | const { register } = useForm();
153 |
154 | return (
155 |
160 | );
161 | }
162 | ```
163 |
--------------------------------------------------------------------------------
/docs/pages/createform/creating-forms/onchange-form.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: OnChange mode
3 | description: When using controlled forms, the input value is set to state values and then updated via React events. React form controlled is the most popular aproach in reactjs.
4 | tags: react, form, useform, use-form, hook, controlled-form, controlled
5 | ---
6 |
7 | import Callout from "../../../components/Callout";
8 | import { FormDemo } from "../../../components/OnChangeDemo";
9 | import { Tab, Tabs } from "../../../components/Tabs";
10 |
11 | # OnChange mode
12 |
13 |
14 |
15 |
16 |
17 |
18 | ```jsx
19 | import { createForm } from "@createform/react";
20 | import { z } from "zod";
21 |
22 | const useForm = createForm({
23 | initialValues: {
24 | email: "",
25 | password: "",
26 | terms: false,
27 | },
28 | mode: "onChange",
29 | validationSchema: z.object({
30 | email: z.string().email(),
31 | password: z.string().min(8),
32 | terms: z.boolean(),
33 | }),
34 | });
35 |
36 | function FormDemo() {
37 | const { register, state } = useForm();
38 | const {errors, touched} = state;
39 |
40 | function handleSubmit(data){console.log(data)}
41 |
42 | return (
43 |
96 | )
97 | }
98 | ```
99 |
100 |
101 |
102 | ## Description
103 |
104 | There are two types of form input in React. We have the uncontrolled input and the controlled input.
105 | When using controlled forms, the input value is set to state values and then updated via React events.
106 | Defining a form input value via state is considered a controlled component. For controlled inputs, you will need a corresponding state and then a function to update that state with changes.
107 |
108 | Controlled inputs are the most popular in the react ecosystem, are easier to write and understanding. But when you think about performance controlled inputs are less powerful than uncontrolled inputs.Every time that component state is updated the component is rendered again and this affects the performance result.
109 |
110 | ## Usage
111 |
112 | Createform provides a `register` function, this function returns all properties to manager a field.
113 |
114 | ```jsx copy
115 | import { createForm } from "@createform/react";
116 |
117 | const useForm = createForm({
118 | initialValues: {
119 | name: "Anna",
120 | address: [
121 | {
122 | street: "123 Main St",
123 | city: "Anytown",
124 | },
125 | ],
126 | },
127 | mode: "onChange",
128 | });
129 | ````
130 |
131 | ```javascript
132 | const test = "";
133 | ```
134 |
135 | Use dot notation to create advanced objects or to map object values. Type an entry name and type or an entry property object.
136 |
137 |
138 |
139 | - Dot notation is used to access nested objects. For example, if you have an object with a nested object, you can access the nested object using dot notation; `info.name`.
140 | - Use dot notation to access nested arrays. For example, if you
141 | - have an object with a nested array, you can access the nested array using dot notation; `info.array[2]`.
142 |
143 |
144 |
145 | ```jsx copy
146 | function Form() {
147 | const { register } = useForm();
148 |
149 | return (
150 |
155 | );
156 | }
157 | ```
158 |
--------------------------------------------------------------------------------
/docs/pages/createform/form-submission.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Form submission
3 | description: This doc helps you how to submit a form using createForm.
4 | tags: react, form, useform, createform, hook, loadData
5 | ---
6 |
7 | import Callout from "../../components/Callout";
8 |
9 | # Introduction
10 |
11 | Once a user fills out a form, it needs to be submitted to the server. There are multiple ways to achieve this. Let's explore how to make it work.
12 |
13 | ## Submit form when deffining the form
14 |
15 | You can configure the form submission when defining the form by using the onSubmit property of createForm. This property will be called when the form is submitted.
16 |
17 | ```jsx
18 | import { createForm } from "@createform/react";
19 |
20 | const form = createForm({
21 | onSubmit: async (values) => {
22 | console.log(values);
23 | }
24 | })
25 | ```
26 |
27 | ## Submit form when using the hook form
28 |
29 | Typically, when updating data, the application should redirect to another page. However, in specific cases, you may want to reload the data to display the new information using the reloadData function.
30 |
31 | ```jsx
32 | import { createForm } from "@createform/react";
33 |
34 | const form = createForm({
35 | initialValues: {
36 | name: "",
37 | email: "",
38 | phone: "",
39 | },
40 |
41 | })
42 |
43 | const FormExample = () => {
44 | cont {handleSubmit} = form();
45 |
46 | return (
47 |
52 | )
53 | }
54 | ```
55 |
56 | ## Conclusion
57 |
58 | You now have a better understanding of how to submit a form using createForm. The choice of how to submit the form is up to you.
--------------------------------------------------------------------------------
/docs/pages/createform/testing/testing-on-change.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Testing onChange forms
3 | description: Testing a form created with Createform in onChange mode is easy and straightforward. Here are some tips for testing your forms.
4 | tags: react, form, useform, createform, use-form, hook, testing, testing-lirary
5 | ---
6 |
7 | import Callout from "../../../components/Callout";
8 |
9 | # Testing onChange forms
10 |
11 | Testing is an important aspect of software development that helps to ensure the correctness and reliability of the code. When it comes to forms, testing becomes even more important, as it involves user interaction and input validation.
12 |
13 | Createform is a powerful library for creating forms in React. One of the modes that Createform supports is onChange, which means that the form will only show error messages when the form is submitted. This mode is useful for validating user input before submitting the form.
14 |
15 | Testing a form created with Createform in onChange mode is easy and straightforward. Here are some tips for testing your forms:
16 |
17 | - Start with simple tests: Begin by testing the most basic functionality of your form, such as ensuring that the form renders correctly and that the initial values are set properly.
18 |
19 | - Test form submission: Test submitting the form with both valid and invalid input. Ensure that the form submission works as expected, and that the form shows error messages when invalid input is entered.
20 |
21 | - Test error messages: Test that the form displays the correct error messages when invalid input is entered. Make sure that the error messages are specific and clear, and that they appear next to the input field where the error occurred.
22 |
23 | - Test reset button: Test the reset button to ensure that it clears the form and resets it to its initial values.
24 |
25 | - Test form validation: Test that the form validation works as expected, both on the client side and on the server side if applicable.
26 |
27 | ## Let's remember some steps to write good tests
28 |
29 |
30 | 1- Import the necessary libraries:
31 |
32 | ```jsx
33 | import { createForm } from "@createform/react";
34 | import { z } from "zod";
35 | import { render, screen, fireEvent } from "@testing-library/react";
36 | import userEvent from "@testing-library/user-event";
37 | ```
38 |
39 | 2 - Define the form using `createForm` with the `onChange` mode:
40 |
41 | ```jsx
42 | const useForm = createForm({
43 | initialValues: {
44 | email: "",
45 | },
46 | mode: "onChange",
47 | validationSchema: z.object({
48 | email: z.string().email(),
49 | }),
50 | });
51 | ```
52 | 3 - Render the form component and get its elements:
53 |
54 | ```jsx
55 | render();
56 | const emailInput = screen.getByLabelText("Your email");
57 | ```
58 |
59 | 4 - Fill in the form with valid data and submit it:
60 |
61 | ```jsx
62 | userEvent.type(emailInput, "test@example.com");
63 | userEvent.blur(emailInput);
64 | ```
65 |
66 | 5 - Assert that there are no error messages displayed:
67 |
68 | ```jsx
69 | expect(screen.queryByText("Please enter a valid email address.")).toBeNull();
70 | ```
71 |
72 | 6 - Fill in the form with invalid data and submit it:
73 |
74 | ```jsx
75 | userEvent.clear(emailInput);
76 | userEvent.type(emailInput, "invalidemail");
77 | userEvent.blur(emailInput);
78 | ```
79 |
80 | 7 - Assert that the appropriate error messages are displayed:
81 |
82 | ```jsx
83 | expect(screen.getByText("Please enter a valid email address.")).toBeInTheDocument();
84 | ```
85 |
86 | 8 - Reset the form and assert that it has been cleared:
87 |
88 | ```jsx
89 | const resetButton = screen.getByText("Reset");
90 | userEvent.click(resetButton);
91 | expect(emailInput).toHaveValue("");
92 | ```
93 |
94 | ## Writing some tests
95 |
96 |
97 | In `onChange` mode, validation is triggered after the blur event, which means that we need to simulate this event in order to test if the expected behavior is true.
98 |
99 |
100 | ```jsx
101 | import { render, screen, fireEvent } from '@testing-library/react';
102 | import { Form } from './your-form';
103 |
104 | describe('Form', () => {
105 | it('displays error message if email is not valid', async () => {
106 | render();
107 | const emailInput = screen.getByLabelText('Your email');
108 | const submitButton = screen.getByRole('button', { name: 'Submit →' });
109 |
110 | fireEvent.change(emailInput, { target: { value: 'invalid-email' } });
111 | userEvent.blur(emailInput);
112 |
113 | const errorMessage = await screen.findByText('Invalid email address');
114 | expect(errorMessage).toBeInTheDocument();
115 | });
116 |
117 | it("clears email error messages on submit", async () => {
118 | render();
119 |
120 | // Fill in invalid email and password
121 | const emailInput = screen.getByLabelText(/your email/i);
122 | fireEvent.change(emailInput, { target: { value: "invalid-email" } });
123 | userEvent.blur(emailInput);
124 |
125 | // Expect error messages to be displayed
126 | expect(await screen.findByText(/invalid email/i)).toBeInTheDocument();
127 |
128 | // Clear error messages
129 | fireEvent.change(emailInput, { target: { value: "valid-email@example.com" } });
130 | userEvent.blur(emailInput);
131 |
132 | // Expect error messages to be cleared
133 | expect(screen.queryByText(/invalid email/i)).not.toBeInTheDocument();
134 | });
135 | });
136 | ```
--------------------------------------------------------------------------------
/docs/pages/createform/using-your-form/native-elements.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Native HTML elements
3 | description: Learn how to use native HTML elements in order to create better forms.
4 | tags: react, form, useform, createform, use-form, debounce, debounced, hook, native-forms, html, input, select, radio, checkbox
5 | ---
6 |
7 | import { FormDemo } from "../../../components/NativeDemo";
8 | import { Tab, Tabs } from "../../../components/Tabs";
9 |
10 | # Native HTML elements
11 |
12 |
13 |
14 |
15 |
16 |
17 | ```jsx
18 | import { createForm } from "@createform/react";
19 | import { z } from "zod";
20 |
21 | const useForm = createForm({
22 | initialValues: {
23 | email: "",
24 | },
25 | mode: "onChange",
26 | });
27 |
28 | function FormDemo() {
29 | const { register, state } = useForm();
30 | const {errors, touched} = state
31 |
32 | function handleSubmit(data){console.log(data)}
33 |
34 | return (
35 |
51 | )
52 | }
53 | ```
54 |
55 |
56 |
57 | ## What is a native HTML element?
58 |
59 | Native HTML elements are elements that are built into the browser, like ``, `