Skip to main content

formisch

Form handling with Formisch, the schema-first and type-safe form library for Angular, Preact, Qwik, React, React Native, Solid, Svelte, and Vue. Use when creating forms, handling form state, validating inputs, working with field arrays, or using @formisch/* packages.

Quellinformationen

Repository
open-circle/agent-skills
Letzte Quellaktivität
21. August 2026 um 21:16
Erkannte Sprache von SKILL.md
Englisch
Sterne
16
Forks
1

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
2 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
formisch
description
Form handling with Formisch, the schema-first and type-safe form library for Angular, Preact, Qwik, React, React Native, Solid, Svelte, and Vue. Use when creating forms, handling form state, validating inputs, working with field arrays, or using @formisch/* packages.
license
MIT
metadata
{"author":"open-circle","version":"1.3"}
# Formisch This skill helps AI agents work effectively with [Formisch](https://formisch.dev/), the schema-based, headless form library for modern frameworks. ## When to Use This Skill - When the user asks about form handling with Formisch - When managing form state and validation - When working with Angular, Preact, Qwik, React, React Native, Solid, Svelte, or Vue forms - When integrating Valibot schemas with forms ## Introduction Formisch is a schema-based, headless form library that works across multiple frameworks. Key highlights: - **Small bundle size** — Starting at ~2.5 kB - **Schema-based validation** — Uses Valibot for type-safe validation - **Headless design** — You control the UI completely - **Type safety** — Full TypeScript support with autocompletion - **Framework-native** — Native performance for each supported framework ### Supported Frameworks | Framework | Package | Hook/Primitive | | ------------ | ------------------------ | -------------- | | Angular | `@formisch/angular` | `injectForm` | | Preact | `@formisch/preact` | `useForm` | | Qwik | `@formisch/qwik` | `useForm$` | | React | `@formisch/react` | `useForm` | | React Native | `@formisch/react-native` | `useForm` | | SolidJS | `@formisch/solid` | `createForm` | | Svelte | `@formisch/svelte` | `createForm` | | Vue | `@formisch/vue` | `useForm` | ## Installation ### 1. Install Valibot (peer dependency) ```bash npm install valibot ``` ### 2. Install Formisch for your framework ```bash npm install @formisch/react # React npm install @formisch/angular # Angular npm install @formisch/vue # Vue npm install @formisch/solid # SolidJS npm install @formisch/preact # Preact npm install @formisch/svelte # Svelte npm install @formisch/qwik # Qwik npm install @formisch/react-native # React Native ``` ## Core Concepts ### Schema-First Design Every form starts with a Valibot schema. Types are automatically inferred from the schema. ```ts import * as v from "valibot"; const LoginSchema = v.object({ email: v.pipe( v.string("Please enter your email."), v.nonEmpty("Please enter your email."), v.email("The email address is badly formatted."), ), password: v.pipe( v.string("Please enter your password."), v.nonEmpty("Please enter your password."), v.minLength(8, "Your password must have 8 characters or more."), ), }); ``` ### Form Store The form store manages all form state. Access it via the framework-specific hook/primitive. **Form Store Properties:** - `isSubmitting` — Form is currently being submitted - `isSubmitted` — Form submission has been attempted - `isValidating` — Validation is in progress - `isTouched` — At least one field has been touched - `isEdited` — At least one field has been edited - `isDirty` — At least one field differs from initial value - `isValid` — All fields pass validation - `errors` — Root-level validation errors ### Field Store Each field has its own reactive store with: - `path` — Path array to the field - `input` — Current field value - `errors` — Field-specific errors - `isTouched` — Field has been focused - `isEdited` — Field value has been edited - `isDirty` — Field value differs from initial value - `isValid` — Field passes validation - `props` — Props to spread onto native elements (Angular connects controls with `[formischControl]` instead) - `onChange` (React and React Native) / `onInput` (Solid, Svelte, Preact, and Qwik) / `setInput` (Angular) — Sets the field input value programmatically. Use this when the field cannot be connected to a native element. In Vue, set `field.input` directly (for example with `v-model`). Store reactivity is framework-specific. React, React Native, Solid, Svelte, and Vue expose plain reactive properties. Angular properties are signals and are called like `field.errors()`, except `path`, which is a plain value. Preact and Qwik properties are signals; use `.value` in conditions and ordinary TypeScript logic. Do not copy one framework's access syntax into another. ### Dirty Tracking Formisch tracks two inputs per field: - **Initial input** — Baseline for dirty tracking (server state) - **Current input** — What the user is editing (client state) `isDirty` becomes `true` when current input differs from initial input. ## Framework Examples ### Angular Example Angular uses signals, dependency injection, and directives instead of a JSX component API. ```ts import { Component } from "@angular/core"; import { FormischControl, FormischField, FormischForm, injectForm, type SubmitHandler, } from "@formisch/angular"; import * as v from "valibot"; const LoginSchema = v.object({ email: v.pipe(v.string(), v.email()), password: v.pipe(v.string(), v.minLength(8)), }); @Component({ selector: "app-login", imports: [FormischForm, FormischField, FormischControl], template: ` <form [formischForm]="loginForm" [formischSubmit]="handleSubmit"> <ng-container *formischField="['email'] of loginForm; let field"> <input [formischControl]="field" type="email" /> @if (field.errors(); as errors) { <div>{{ errors[0] }}</div> } </ng-container> <button type="submit" [disabled]="loginForm.isSubmitting()">Login</button> </form> `, }) export class LoginComponent { readonly loginForm = injectForm({ schema: LoginSchema }); readonly handleSubmit: SubmitHandler<typeof LoginSchema> = (output) => { console.log(output); }; } ``` Let `[formischControl]` synchronize the native control. Do not add competing `[value]` or `[checked]` bindings except when `value` identifies an option in a radio or checkbox group. ### React Native Example React Native has no DOM `<form>` element or Formisch `Form` component. Use `handleSubmit` and bind `field.props` to `TextInput`. ```tsx import { Field, handleSubmit, useForm } from "@formisch/react-native"; import { Button, TextInput, View } from "react-native"; import * as v from "valibot"; const LoginSchema = v.object({ email: v.pipe(v.string(), v.email()), password: v.pipe(v.string(), v.minLength(8)), }); export default function LoginScreen() { const loginForm = useForm({ schema: LoginSchema }); const submitForm = handleSubmit(loginForm, (output) => console.log(output)); return ( <View> <Field of={loginForm} path={["email"]}> {(field) => ( <TextInput {...field.props} value={field.input} autoCapitalize="none" keyboardType="email-address" /> )} </Field> <Field of={loginForm} path={["password"]}> {(field) => ( <TextInput {...field.props} value={field.input} secureTextEntry /> )} </Field> <Button title="Login" onPress={submitForm} /> </View> ); } ``` React Native text inputs are controlled, so always pass `value={field.input}`. Use `field.onChange(value)` for switches, sliders, pickers, and non-string values. ### React Example ```tsx import { Field, Form, useForm } from "@formisch/react"; import type { SubmitHandler } from "@formisch/react"; import * as v from "valibot"; const LoginSchema = v.object({ email: v.pipe(v.string(), v.email()), password: v.pipe(v.string(), v.minLength(8)), }); export default function LoginPage() { const loginForm = useForm({ schema: LoginSchema, }); const handleSubmit: SubmitHandler<typeof LoginSchema> = (output) => { console.log(output); // { email: string, password: string } }; return ( <Form of={loginForm} onSubmit={handleSubmit}> <Field of={loginForm} path={["email"]}> {(field) => ( <div> <input {...field.props} value={field.input} type="email" /> {field.errors && <div>{field.errors[0]}</div>} </div> )} </Field> <Field of={loginForm} path={["password"]}> {(field) => ( <div> <input {...field.props} value={field.input} type="password" /> {field.errors && <div>{field.errors[0]}</div>} </div> )} </Field> <button type="submit" disabled={loginForm.isSubmitting}> {loginForm.isSubmitting ? "Submitting..." : "Login"} </button> </Form> ); } ``` ### Vue Example ```vue <script setup lang="ts"> import { Field, Form, useForm } from "@formisch/vue"; import type { SubmitHandler } from "@formisch/vue"; import * as v from "valibot"; const LoginSchema = v.object({ email: v.pipe(v.string(), v.email()), password: v.pipe(v.string(), v.minLength(8)), }); const loginForm = useForm({ schema: LoginSchema, }); const handleSubmit: SubmitHandler<typeof LoginSchema> = (output) => { console.log(output); }; </script> <template> <Form :of="loginForm" @submit="handleSubmit"> <Field :of="loginForm" :path="['email']" v-slot="field"> <div> <input v-model="field.input" v-bind="field.props" type="email" /> <div v-if="field.errors">{{ field.errors[0] }}</div> </div> </Field> <Field :of="loginForm" :path="['password']" v-slot="field"> <div> <input v-model="field.input" v-bind="field.props" type="password" /> <div v-if="field.errors">{{ field.errors[0] }}</div> </div> </Field> <button type="submit">Login</button> </Form> </template> ``` ### SolidJS Example ```tsx import { Field, Form, createForm } from "@formisch/solid"; import type { SubmitHandler } from "@formisch/solid"; import * as v from "valibot"; const LoginSchema = v.object({ email: v.pipe(v.string(), v.email()), password: v.pipe(v.string(), v.minLength(8)), }); export default function LoginPage() { const loginForm = createForm({ schema: LoginSchema, }); const handleSubmit: SubmitHandler<typeof LoginSchema> = (output) => { console.log(output); }; return ( <Form of={loginForm} onSubmit={handleSubmit}> <Field of={loginForm} path={["email"]}> {(field) => ( <div> <input {...field.props} value={field.input} type="email" /> {field.errors && <div>{field.errors[0]}</div>} </div> )} </Field> <Field of={loginForm} path={["password"]}> {(field) => ( <div> <input {...field.props} value={field.input} type="password" /> {field.errors && <div>{field.errors[0]}</div>} </div> )} </Field> <button type="submit">Login</button> </Form> ); } ``` ### Svelte Example ```svelte <script lang="ts"> import { createForm, Field, Form } from '@formisch/svelte'; import type { SubmitHandler } from '@formisch/svelte'; import * as v from 'valibot';
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen