### Start Development Server Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/README.md Navigate to the website directory and start the development server. ```bash cd ../../website && pnpm dev ``` -------------------------------- ### Start Development Server Source: https://github.com/fabian-hiller/modular-forms/blob/main/playgrounds/solid/README.md Navigate to the SolidJS playground directory and start the development server. ```bash cd ../../playgrounds/solid && pnpm dev ``` -------------------------------- ### Initialize Form with Components - Solid Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/create-your-form.mdx Demonstrates initializing a form using `createForm` in Solid and destructuring the returned tuple to get the `Form` and `Field` components. This setup is the first step in rendering a form. ```tsx import { createForm } from '@modular-forms/solid'; type LoginForm = { email: string; password: string; }; export default function App() { const [loginForm, { Form, Field }] = createForm(); return
; } ``` -------------------------------- ### Start Development Server Source: https://github.com/fabian-hiller/modular-forms/blob/main/playgrounds/react/README.md Start the development server for the React playground. ```bash cd ../../playgrounds/react && pnpm dev ``` -------------------------------- ### Install Dependencies Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/README.md Install all project dependencies using pnpm. ```bash pnpm install ``` -------------------------------- ### Start Qwik Development Server Source: https://github.com/fabian-hiller/modular-forms/blob/main/playgrounds/qwik/README.md Start the development server for the Qwik playground. This command should be run from the root of the cloned repository after building the package. ```bash cd ../../playgrounds/qwik && pnpm dev ``` -------------------------------- ### Start Preact Development Server Source: https://github.com/fabian-hiller/modular-forms/blob/main/playgrounds/preact/README.md Start the development server for the Preact playground. Ensure you are in the correct directory before executing this command. ```bash cd ../../playgrounds/preact && pnpm dev ``` -------------------------------- ### Initialize Form with Components - Preact Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/create-your-form.mdx Illustrates how to initialize a form in Preact using `useForm` and destructuring the hook's return value to get the `Form` component. This is the initial setup for rendering a form structure. ```tsx import { useForm } from '@modular-forms/preact'; type LoginForm = { email: string; password: string; }; export default function App() { const [loginForm, { Form, Field }] = useForm(); return
; } ``` -------------------------------- ### Build @modular-forms/solid Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/README.md Build the @modular-forms/solid package after installing dependencies. ```bash cd packages/solid && pnpm build ``` -------------------------------- ### Form Component Usage Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/Form.mdx Examples of using the Form component in Solid/Preact/React and Qwik. ```APIDOC ## Form Component ### Description The Form component is a versatile element designed to manage form validation and streamline the submission process. It provides a unified interface for handling form state and actions across different frontend frameworks. ### Usage Examples #### Solid, Preact, or React ```tsx
children
``` #### Qwik ```tsx
children
``` ### Properties All frameworks share the following properties: - `of` (any): The schema or form state object. - `keepResponse` (boolean): Determines if the response should be kept after submission. - `shouldActive` (boolean): Enables active validation. - `shouldTouched` (boolean): Enables validation when fields are touched. - `shouldDirty` (boolean): Enables validation when fields are dirty. - `shouldFocus` (boolean): Enables focus on the first invalid field upon validation error. - `children` (ReactNode | JSX.Element): The content to be rendered within the form. #### Solid, Preact, or React Specific Properties: - `onSubmit` (function): Callback function executed upon form submission. #### Qwik Specific Properties: - `action` (string): The URL to which the form data will be submitted. - `onSubmit$` (function): A Qwik-specific callback function for handling form submission. - `encType` (string): Specifies the content type for form submission (e.g., `application/x-www-form-urlencoded`). - `reloadDocument` (boolean): If true, the entire document will be reloaded after submission. ``` -------------------------------- ### Install Modular Forms for Qwik Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/installation.mdx Use this command to add the Qwik version of Modular Forms to your project. ```bash npm install @modular-forms/qwik ``` -------------------------------- ### Login Form with Valibot Validation (Qwik) Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/validate-your-fields.mdx Use `valiForm$` for Qwik applications to integrate Valibot schemas. This example includes route loader setup for initial form values. ```tsx import { $, component$ } from '@builder.io/qwik'; import { routeLoader$ } from '@builder.io/qwik-city'; import { type InitialValues, useForm, valiForm$ } from '@modular-forms/qwik'; import * as v from 'valibot'; const LoginSchema = v.object({ email: v.pipe( v.string(), v.nonEmpty('Please enter your email.'), v.email('The email address is badly formatted.') ), password: v.pipe( v.string(), v.nonEmpty('Please enter your password.'), v.minLength(8, 'You password must have 8 characters or more.') ), }); type LoginForm = v.InferInput; export const useFormLoader = routeLoader$>(() => ({ email: '', password: '', })); export default component$(() => { const [loginForm, { Form, Field }] = useForm({ loader: useFormLoader(), validate: valiForm$(LoginSchema), }); return (
{(field, props) => ( <> {field.error &&
{field.error}
} )}
{(field, props) => ( <> {field.error &&
{field.error}
} )}
); }); ``` -------------------------------- ### Build @modular-forms/qwik Package Source: https://github.com/fabian-hiller/modular-forms/blob/main/playgrounds/qwik/README.md Build the `@modular-forms/qwik` package. This step is required before starting the development server for the Qwik playground. ```bash cd packages/qwik && pnpm build ``` -------------------------------- ### Install Modular Forms for Solid Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/installation.mdx Use this command to add the Solid.js version of Modular Forms to your project. ```bash npm install @modular-forms/solid ``` -------------------------------- ### Install Kobalte Core Package Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/kobalte.mdx Add the Kobalte core package to your project using npm, yarn, or pnpm. ```bash npm install @kobalte/core ``` -------------------------------- ### Install Modular Forms for React Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/installation.mdx Use this command to add the React version of Modular Forms to your project. ```bash npm install @modular-forms/react ``` -------------------------------- ### Install Modular Forms for Preact Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/installation.mdx Use this command to add the Preact version of Modular Forms to your project. ```bash npm install @modular-forms/preact ``` -------------------------------- ### Login Form with Valibot Validation (React) Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/validate-your-fields.mdx Use `valiForm` for React applications to implement Valibot schema validation. This example demonstrates the basic setup for a login form. ```tsx import { useForm, valiForm } from '@modular-forms/react'; import * as v from 'valibot'; const LoginSchema = v.object({ email: v.pipe( v.string(), v.nonEmpty('Please enter your email.'), v.email('The email address is badly formatted.') ), password: v.pipe( v.string(), v.nonEmpty('Please enter your password.'), v.minLength(8, 'You password must have 8 characters or more.') ), }); type LoginForm = v.InferInput; export default function App() { const [loginForm, { Form, Field }] = useForm({ validate: valiForm(LoginSchema), }); return (
{(field, props) => ( <> {field.error &&
{field.error}
} )}
{(field, props) => ( <> {field.error &&
{field.error}
} )}
); } ``` -------------------------------- ### Import Modular Forms in Qwik Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/installation.mdx Example import statement for using Modular Forms within a Qwik project. ```typescript import { … } from '@modular-forms/qwik'; ``` -------------------------------- ### Import Modular Forms in Solid Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/installation.mdx Example import statement for using Modular Forms within a Solid.js project. ```typescript import { … } from '@modular-forms/solid'; ``` -------------------------------- ### Initialize form with initial values in Qwik Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/create-your-form.mdx Use `routeLoader$` to define initial values for your form, especially for server-side rendering. This ensures Qwik can reliably start rendering your website on the server. ```typescript import { routeLoader$, } from '@builder.io/qwik-city'; import { type InitialValues } from '@modular-forms/qwik'; type LoginForm = { email: string; password: string; }; export const useFormLoader = routeLoader$>(() => { return { email: '', password: '', }; }); ``` -------------------------------- ### Build @modular-forms/preact Package Source: https://github.com/fabian-hiller/modular-forms/blob/main/playgrounds/preact/README.md Build the Preact package after installing dependencies. Navigate to the correct directory before running the build command. ```bash cd packages/preact && pnpm build ``` -------------------------------- ### Login Form with Field Validation Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/validate-your-fields.mdx Example of a login form demonstrating field validation for username and password. It uses 'required' and 'minLength' validators. ```jsx function LoginForm() { return (
{(field, props) => ( <> {field.error &&
{field.error}
} )}
{(field, props) => ( <> {field.error &&
{field.error}
} )}
); } ``` -------------------------------- ### Import Modular Forms in React Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/installation.mdx Example import statement for using Modular Forms within a React project. ```typescript import { … } from '@modular-forms/react'; ``` -------------------------------- ### Install Preact Signals-React Peer Dependency Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/installation.mdx Required peer dependency for using Modular Forms with React. Refer to the `@preact/signals-react` README for proper configuration. ```bash npm install @preact/signals-react ``` -------------------------------- ### Import Modular Forms in Preact Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/installation.mdx Example import statement for using Modular Forms within a Preact project. ```typescript import { … } from '@modular-forms/preact'; ``` -------------------------------- ### Install Preact Signals Peer Dependency Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/installation.mdx Required peer dependency for using Modular Forms with Preact. Consult the official documentation for configuration details. ```bash npm install @preact/signals ``` -------------------------------- ### Login Form with Valibot Validation (Preact) Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/validate-your-fields.mdx Integrate Valibot validation into your Preact forms using the `valiForm` adapter. Ensure Valibot is installed and imported. ```tsx import { useForm, valiForm } from '@modular-forms/preact'; import * as v from 'valibot'; const LoginSchema = v.object({ email: v.pipe( v.string(), v.nonEmpty('Please enter your email.'), v.email('The email address is badly formatted.') ), password: v.pipe( v.string(), v.nonEmpty('Please enter your password.'), v.minLength(8, 'You password must have 8 characters or more.') ), }); type LoginForm = v.InferInput; export default function App() { const [loginForm, { Form, Field }] = useForm({ validate: valiForm(LoginSchema), }); return (
{(field, props) => ( <> {field.error &&
{field.error}
} )}
{(field, props) => ( <> {field.error &&
{field.error}
} )}
); } ``` -------------------------------- ### Login Form with Valibot Validation (Solid) Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/validate-your-fields.mdx Use `valiForm` to define the validation schema for the entire form with Valibot. Ensure Valibot is installed and imported. ```tsx import { createForm, valiForm } from '@modular-forms/solid'; import * as v from 'valibot'; const LoginSchema = v.object({ email: v.pipe( v.string(), v.nonEmpty('Please enter your email.'), v.email('The email address is badly formatted.') ), password: v.pipe( v.string(), v.nonEmpty('Please enter your password.'), v.minLength(8, 'You password must have 8 characters or more.') ), }); type LoginForm = v.InferInput; export default function App() { const [loginForm, { Form, Field }] = createForm({ validate: valiForm(LoginSchema), }); return (
{(field, props) => ( <> {field.error &&
{field.error}
} )}
{(field, props) => ( <> {field.error &&
{field.error}
} )}
); } ``` -------------------------------- ### Example form type definition (Qwik) Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/define-your-form.mdx Define a TypeScript type for a form in Qwik, using `NoSerialize` for Blob types. This ensures type safety and proper handling of file uploads within the Qwik framework. ```typescript type SpecialForm = { number: number; range: number; checkbox: { array: string[]; boolean: boolean; }; select: { array: string[]; string?: string; }; file: { list: NoSerialize[]; item?: NoSerialize; }; }; ``` -------------------------------- ### Destructure Form Components - Qwik Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/create-your-form.mdx Shows how to destructure the result of `useForm` in Qwik to get form components for separate forms like `Login` and `Register`. This pattern is beneficial for managing multiple forms on a single page. ```tsx export default component$(() => { const [, Login] = useForm({ loader: useLoginLoader() }); const [, Register] = useForm({ loader: useRegisterLoader() }); return ( <> ); }); ``` -------------------------------- ### Initialize Form with Components - Qwik Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/create-your-form.mdx Shows the initialization of a form in Qwik using `useForm` and destructuring the result to obtain the `Form` component. This is a foundational step for rendering form elements. ```tsx export default component$(() => { const [loginForm, { Form, Field }] = useForm({ loader: useFormLoader(), }); return
; }); ``` -------------------------------- ### Build React Package Source: https://github.com/fabian-hiller/modular-forms/blob/main/playgrounds/react/README.md Build the `@modular-forms/react` package. ```bash cd packages/react && pnpm build ``` -------------------------------- ### Initialize form with static initial values in Qwik Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/create-your-form.mdx For static initial values, you can use `useSignal` or a normal JavaScript object with a `value` key if the form is deeper in the component tree. Note: DX for static values is planned for future improvement. ```typescript const [loginForm, { Form, Field }] = useForm({ loader: { value: { email: '', password: '' } }, }); ``` -------------------------------- ### Initialize Form with Components - React Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/create-your-form.mdx Demonstrates initializing a form in React with `useForm` and destructuring the output to access the `Form` component. This is the basic structure required to render a form. ```tsx import { useForm } from '@modular-forms/react'; type LoginForm = { email: string; password: string; }; export default function App() { const [loginForm, { Form, Field }] = useForm(); return
; } ``` -------------------------------- ### Reusable `toCents` Transformation (Qwik) Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/transform-inputs.mdx Creates a reusable transformation function to convert values to cents for storage. Uses the 'input' event for transformation. ```ts import type { Maybe, MaybeValue, TransformField } from '@modular-forms/qwik'; import { toCustom$ } from '@modular-forms/qwik'; export function toCents>(): TransformField { return toCustom$( (value) => value && ((value * 100) as Maybe), { on: 'input' } ); } ``` -------------------------------- ### Create Form Store Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/useFormStore.mdx Use `useFormStore` to initialize the form's state. Define generic types for `Values` and `ResponseData` for type safety and autocompletion. The `options` parameter configures the form's behavior. ```typescript const form = useFormStore(options); ``` -------------------------------- ### Get Form Errors Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/getErrors.mdx Use getErrors to retrieve errors for all fields in the form. Pass the form store and optional configuration options. ```typescript const errors = getErrors(form, options); ``` -------------------------------- ### Get Form Values with getValues Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/getValues.mdx Use getValues to retrieve the current values of form fields. You can optionally provide options to filter the results. ```typescript const values = getValues(form, options); ``` -------------------------------- ### Form Component Usage (Solid/Preact/React) Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/Form.mdx Demonstrates the basic usage of the Form component in Solid, Preact, or React applications. Use this for standard form handling with validation. ```tsx
children
``` -------------------------------- ### Basic Field Structure (Solid/Qwik/Preact) Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/input-components.mdx Illustrates a basic form field structure using the Field component, suitable for Solid, Qwik, or Preact. It shows how to render a label, input, and error message. ```tsx {(field, props) => (
{field.error &&
{field.error}
}
)}
``` -------------------------------- ### FormOptions for Qwik Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/FormOptions.mdx Defines the options for a form when using Qwik. Includes loader, action, validation, and field array configurations. ```APIDOC ## FormOptions (Qwik) ### Description Configuration options for a form in Qwik, including data loading, actions, validation, and field array management. ### Properties - **loader** (object) - Data loader for the form. - **action** (object) - Action handler for form submissions. - **validate** (function) - A function to validate the form's current values. - **validateOn** (string) - When to trigger validation (e.g., 'blur', 'submit'). - **revalidateOn** (string) - When to revalidate the form values. - **fieldArrays** (object) - Configuration for managing dynamic field arrays within the form. ``` -------------------------------- ### Create Email Validation Function Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/email.mdx Creates a validation function for email addresses. Pass an error message string to the email function to get a validator. ```typescript const validate = email(error); ``` -------------------------------- ### Handle submission with Qwik's onSubmit$ Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/handle-submission.mdx For Qwik, use `onSubmit$` on the `Form` component to handle client-side submissions. This integrates with Qwik's event handling system. ```tsx import { $, component$, QRL } from '@builder.io/qwik'; import { routeLoader$ } from '@builder.io/qwik-city'; import { InitialValues, formAction$, valiForm$, } from '@modular-forms/qwik'; import * as v from 'valibot'; const LoginSchema = v.object({ email: v.pipe( v.string(), v.nonEmpty('Please enter your email.'), v.email('The email address is badly formatted.') ), password: v.pipe( v.string(), v.nonEmpty('Please enter your password.'), v.minLength(8, 'You password must have 8 characters or more.') ), }); type LoginForm = v.InferInput; export const useFormLoader = routeLoader$>(() => ({ email: '', password: '', })); export const useFormAction = formAction$((values) => { // Runs on server }, valiForm$(LoginSchema)); export default component$(() => { const [loginForm, { Form, Field }] = useForm({ loader: useFormLoader(), action: useFormAction(), validate: valiForm$(LoginSchema), }); const handleSubmit: QRL> = $((values, event) => { // Runs on client }); return
; }); ``` -------------------------------- ### Clone Repository Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/README.md Use this command to clone the modular-forms repository from GitHub. ```bash git clone git@github.com:fabian-hiller/modular-forms.git ``` -------------------------------- ### Move Field Array Item Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/field-arrays.mdx Example of using the 'move' method to rearrange items within a field array. This method automatically handles the rearrangement of fields in between. ```typescript move(todoForm, 'todos', { from: 0, to: 2 }); ``` -------------------------------- ### Get Specific Field Errors Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/getErrors.mdx Fetch errors for a defined list of fields by passing their names to the getErrors function along with the form store and optional configuration. ```typescript const errors = getErrors(form, names, options); ``` -------------------------------- ### toCustom$ Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/toCustom$.mdx Creates a custom transformation function by taking an action and optional configuration. ```APIDOC ## toCustom$ ### Description Creates a custom transformation function. ### Parameters - `action` (TransformField) - The action to perform. - `options` (object) - Optional configuration for the transformation. - `on` (string) - The event to listen for. Possible values: 'input', 'change', 'blur'. ### Return - `transform` (QRL) - The created transformation function. ``` -------------------------------- ### Form Component Usage (Qwik) Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/Form.mdx Illustrates the Form component's usage within a Qwik application. This version includes Qwik-specific properties for form submission and behavior. ```tsx
children
``` -------------------------------- ### Get Field Array Values with getValues Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/getValues.mdx Retrieve values from a specific field array by providing its name to the getValues function. Options can be used to filter the results. ```typescript const values = getValues(form, name, options); ``` -------------------------------- ### Initialize form hook in Qwik Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/create-your-form.mdx The `useForm` hook in Qwik takes your loader as an argument to initialize the form state. It returns the form store and the `Form`, `Field`, and `FieldArray` components for managing form elements. ```typescript export default component$(() => { const [loginForm, { Form, Field, FieldArray }] = useForm({ loader: useFormLoader(), }); }); ``` -------------------------------- ### Get Specific Field Values with getValues Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/getValues.mdx Fetch the values of specific fields by passing an array of field names to the getValues function. Options can be used to filter the results. ```typescript const values = getValues(form, names, options); ``` -------------------------------- ### FormOptions for Solid/Preact/React Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/FormOptions.mdx Defines the options for a form when using Solid, Preact, or React. Includes initial values, validation functions, and validation/revalidation triggers. ```APIDOC ## FormOptions (Solid/Preact/React) ### Description Configuration options for a form, including initial values and validation strategies. ### Properties - **initialValues** (object) - The initial state of the form fields. - **validate** (function) - A function to validate the form's current values. - **validateOn** (string) - When to trigger validation (e.g., 'blur', 'submit'). - **revalidateOn** (string) - When to revalidate the form values. ``` -------------------------------- ### Get Field Array Errors Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/getErrors.mdx Retrieve errors for all fields within a specific field array by providing the form store, the field array's name, and optional configuration. ```typescript const errors = getErrors(form, name, options); ``` -------------------------------- ### Login Form Validation with Qwik Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/validate-your-fields.mdx Implement a login form with email and password validation using Qwik. Requires 'required', 'email', and 'minLength' validators. Uses routeLoader for initial values. ```tsx import { component$ } from '@builder.io/qwik'; import { routeLoader$ } from '@builder.io/qwik-city'; import { email, type InitialValues, minLength, required, useForm, } from '@modular-forms/qwik'; type LoginForm = { email: string; password: string; }; export const useFormLoader = routeLoader$>(() => ({ email: '', password: '', })); export default component$(() => { const [loginForm, { Form, Field }] = useForm({ loader: useFormLoader(), }); return (
('Please enter your email.'), email('The email address is badly formatted.'), ]} > {(field, props) => ( <> {field.error &&
{field.error}
} )}
('Please enter your password.'), minLength(8, 'You password must have 8 characters or more.'), ]} > {(field, props) => ( <> {field.error &&
{field.error}
} )}
); }); ``` -------------------------------- ### Use Radio Group with Modular Forms Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/kobalte.mdx Example of integrating the custom RadioGroup component with Modular Forms' Field component. This demonstrates how to bind form state and handle validation errors. ```tsx {(field, props) => ( )} ``` -------------------------------- ### Type-Safe Form Props with Qwik Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/typescript.mdx Demonstrates type-safe form store props in Qwik using `FormStore` and `useFormStore`. It includes a `routeLoader$` for initial values and defines a `LoginForm` type for the form structure. ```tsx import { component$ } from "@builder.io/qwik"; import { routeLoader$ } from '@builder.io/qwik-city'; import { useFormStore, Form, type FormStore, Field } from '@modular-forms/solid'; type LoginForm = { email: string; password: string; }; export const useFormLoader = routeLoader$>(() => ({ email: '', password: '', })); export default component$(() => { const loginForm = useFormStore({ loader: useFormLoader() }); return }); type FormContentProps { loginForm: FormStore; } const FormContent = component$(({ loginForm }) => (
{(field, props) => } {(field, props) => }
)); ``` -------------------------------- ### Get Field Error Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/getError.mdx Retrieves the error for a given field name. By default, it returns undefined if the field is inactive. Options can modify this behavior to include inactive, untouched, or undirty fields. ```typescript const error = getError(form, name, options); ``` -------------------------------- ### Type-Safe Form Props with Preact Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/typescript.mdx Shows how to achieve type safety for form store props in Preact using the `FormStore` type and `useFormStore`. This example defines a `LoginForm` type for structured form data. ```tsx import { Form, type FormStore, Field, useFormStore } from '@modular-forms/preact'; type LoginForm = { email: string; password: string; } export function LoginPage() { const loginForm = useFormStore(); return } type FormContentProps { loginForm: FormStore; } function FormContent({ loginForm }: FormContentProps) { return (
{(field, props) => } {(field, props) => }
); } ``` -------------------------------- ### FormError Constructor Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/FormError.mdx Demonstrates how to instantiate the FormError class with different combinations of messages and errors. ```APIDOC ## FormError Constructor ### Description Instantiate the `FormError` class to represent form validation issues. It can be used for general messages, specific field errors, or a combination of both. ### Parameters - `message` (string) - Optional - A general error message. - `errors` (FormErrors) - Optional - An object containing field-specific errors. ### Generic - `Values` (FieldValues) - The type of the form values. ### Usage Examples ```typescript // For general errors new FormError(message); // For general and field errors new FormError(message, errors); // For field errors only new FormError(errors); ``` ### Properties - `Values`: Represents the type of the form values. It is a custom type named `FieldValues` and can be further explored at `../FieldValues`. - `errors`: Represents the form errors. It is a custom type named `FormErrors` and can be further explored at `../FormErrors`. ``` -------------------------------- ### Use TextField with Modular Forms Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/kobalte.mdx Integrate the custom TextField component with Modular Forms by using the Field component to manage form state and props. This example shows how to set up an email input field. ```tsx {(field, props) => ( )} ``` -------------------------------- ### formAction$ Usage Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/formAction$.mdx Demonstrates the basic and advanced usage of the formAction$ function with generics for form values and response data. ```APIDOC ## formAction$ ### Description Creates an action for progressively enhanced forms that handles validation and submission on the server. ### Method Signature ```ts // Form action for simple forms formAction$(action, validate); // Form actions for complex forms formAction$(action, options); ``` ### Generics - `Values`: Represents the type of the form field values. - `ResponseData`: Represents the type of the data returned from the action. ### Parameters - `action` (function): A function that is executed if the form values pass validation. It can process form values, interact with a database, and manipulate the form action's state or send messages to the client. - `validate` (QRL): A validation function executed on the server. - `options` (object): An optional object for configuring complex form actions. - `validate` (QRL): The validation function. - `arrays` (Maybe): Supplemental information for array fields. - `booleans` (Maybe): Supplemental information for boolean fields. - `files` (Maybe): Supplemental information for file fields. - `numbers` (Maybe): Supplemental information for number fields. ### Explanation When using TypeScript, defining `Values` allows the library to understand the form's fields and their expected values, enabling autocompletion and type checking. The `action` function is crucial for server-side processing after successful validation. The `arrays`, `booleans`, `files`, and `numbers` options help preserve data when JavaScript is unavailable during form submission. ``` -------------------------------- ### Type-Safe Form Props with Solid Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/typescript.mdx Use the `FormStore` type to ensure type safety when passing form stores as props between components in Solid. This example defines a `LoginForm` type and passes its store to a `FormContent` component. ```tsx import { createFormStore, Form, FormStore, Field } from '@modular-forms/solid'; type LoginForm = { email: string; password: string; } export function LoginPage() { const loginForm = createFormStore(); return } type FormContentProps { loginForm: FormStore; } function FormContent(props: FormContentProps) { return (
{(field, props) => } {(field, props) => }
); } ``` -------------------------------- ### Spread Props to Input Element Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/FieldElementProps.mdx Demonstrates using the spread syntax to pass properties to an HTML input element. This is the intended way to apply props. ```tsx ``` -------------------------------- ### Login Form Validation with Solid Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/validate-your-fields.mdx Implement a login form with email and password validation using Solid. Requires 'required', 'email', and 'minLength' validators. ```tsx import { createForm, email, minLength, required } from '@modular-forms/solid'; type LoginForm = { email: string; password: string; }; export default function App() { const [loginForm, { Form, Field }] = createForm(); return (
{(field, props) => ( <> {field.error &&
{field.error}
} )}
{(field, props) => ( <> {field.error &&
{field.error}
} )}
); } ``` -------------------------------- ### useForm Hook Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/useForm.mdx Creates a form store and associated components. It accepts generic types for form values and response data, and an options object for configuration. It returns the form store and the Form, Field, and FieldArray components, which are pre-linked to the store. ```APIDOC ## useForm ### Description Creates and returns the store of the form as well as a linked Form, Field and FieldArray component. ### Generics - `Values`: Represents the type of the form's field values. - `ResponseData`: Represents the type of the data returned from a form submission. ### Parameters - `options` (FormOptions): Configuration options for the form. ### Return - `form` (FormStore): The reactive store for the form state. - `Form` (Form): A component to render the form. - `Field` (Field): A component to render individual form fields. - `FieldArray` (FieldArray): A component to render array fields. ### Example ```ts const [form, { Form, Field, FieldArray }] = useForm(options); ``` ``` -------------------------------- ### Implement Kobalte Radio Group Component Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/kobalte.mdx This component wraps the Kobalte Radio Group for use with Modular Forms. It handles props like name, label, options, value, and error states. Ensure you have @kobalte/core installed. ```tsx import { RadioGroup as Kobalte } from '@kobalte/core'; import { type JSX, Show, splitProps, For } from 'solid-js'; type RadioGroupProps = { name: string; label?: string | undefined; options: { label: string; value: string }[]; value: string | undefined; error: string; required?: boolean | undefined; disabled?: boolean | undefined; ref: (element: HTMLInputElement | HTMLTextAreaElement) => void; onInput: JSX.EventHandler; onChange: JSX.EventHandler; onBlur: JSX.EventHandler; }; export function RadioGroup(props: RadioGroupProps) { const [rootProps, inputProps] = splitProps( props, ['name', 'value', 'required', 'disabled'], ['ref', 'onInput', 'onChange', 'onBlur'] ); return ( {props.label}
{(option) => ( {option.label} )}
{props.error}
); } ``` -------------------------------- ### Use Kobalte Checkbox with Modular Forms Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/kobalte.mdx Demonstrates integrating the custom Checkbox component with Modular Forms' Field component. This example shows how to bind the checkbox's checked state and error messages to the form field. ```tsx {(field, props) => ( )} ``` -------------------------------- ### Transform Phone Input (Qwik) Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/transform-inputs.mdx Use `toCustom$` with an 'input' event to transform a phone number as the user types in Qwik. The `toCustom$` function provides an `element` reference. ```tsx import { A, Description, Preact, Qwik, React, Solid, SolidOrPreact, SolidPreactOrReact, SolidQwikOrPreact, Title, } from '~/components'; import { Field } from '@modular-forms/qwik'; import { toCustom$ } from '@modular-forms/qwik/transformers'; { // Transform phone number here }, { on: 'input' } )} > {(field, props) => ( )} ``` -------------------------------- ### Transforming Monetary Input (Qwik) Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/transform-inputs.mdx Converts cents to dollars/euros for display and back to cents on input. Requires JavaScript to be enabled. ```tsx value && value * 100, { on: 'input', })}> {(field, props) => { const value = useSignal(); useTask$(({ track }) => { if (!Number.isNaN(track(() => field.value))) { value.value = field.value && field.value / 100; } }); return ; }} ``` -------------------------------- ### Get Field Value Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/getValue.mdx Retrieves the value of a specified field from the form store. By default, it returns undefined if the field is inactive. Options can be used to modify this behavior and return undefined for inactive, untoched, undirty, or invalid fields. ```typescript const value = getValue(form, name, options); ``` -------------------------------- ### Initialize form hook in Preact Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/create-your-form.mdx The `useForm` hook in Preact initializes the form state and returns the form store along with `Form`, `Field`, and `FieldArray` components. This setup is used for managing form elements in Preact applications. ```typescript import { useForm } from '@modular-forms/preact'; type LoginForm = { email: string; password: string; }; export default function App() { const [loginForm, { Form, Field, FieldArray }] = useForm(); } ``` -------------------------------- ### useFormStore Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/api/useFormStore.mdx Creates and returns the store of the form. It is recommended to define your field values using TypeScript for autocompletion and type safety. ```APIDOC ## useFormStore ### Description Creates and returns the store of the form. If you use TypeScript, you should define your field values. This way the library knows exactly which fields your form has and what values they expect. It also allows autocompletion and TypeScript notifies you of typos. > It is recommended to use `type` instead of `interface` as this currently requires an explicit index signature in TypeScript. ### Generics - `Values` (FieldValues): Represents the type of the form's field values. - `ResponseData` (Maybe): Represents the type of the response data, defaults to `undefined`. ### Parameters - `options` (FormOptions): Configuration options for the form store. ### Return - `form` (FormStore): The form store object containing form state and methods. ``` -------------------------------- ### Example form type definition (Solid/Preact/React) Source: https://github.com/fabian-hiller/modular-forms/blob/main/website/src/routes/(layout)/[framework]/guides/define-your-form.mdx Define a TypeScript type for a form that includes various data types like numbers, booleans, strings, arrays, and File objects. This is useful for ensuring type safety in your form components. ```typescript type SpecialForm = { number: number; range: number; checkbox: { array: string[]; boolean: boolean; }; select: { array: string[]; string: string; }; file: { list: File[]; item: File; }; }; ```