A fully type-safe, schema-driven form library that gives you superpowers.
Comes with a minimal composition API that prioritizes developer experience and form correctness.
🚧 this library is not production ready yet.
- Compact API – Minimal yet expressive API surface with core functions like
useForm,register, andhandleSubmitto reduce boilerplate. - Abstract Schema Support – Integrates with validation libraries like Zod for type-safe schemas and automatic validation.
- v-register Directive – One SSR-safe directive that automatically tracks everything.
- Full State Tracking – Automatically tracks field states (value, touched, dirty status, validation errors, etc).
- Reactive Field Errors –
fieldErrorsauto-populates on validation failure and clears on success;setFieldErrorsFromApimaps server 422 envelopes onto fields for inline display. - TypeScript Friendly – Fully type-safe, with advanced form type inference from your schema.
Install with Nuxi:
npx nuxi module add @chemical-x/formsThat's it! You can now use Chemical X Forms in your Nuxt app ✨
Install manually:
# Using npm
npm install @chemical-x/formsThen add the module to your nuxt.config.ts:
export default defineNuxtConfig({
modules: ["@chemical-x/forms"],
});Basic Example
<script setup lang="ts">
import { z } from "zod";
// Define your schema
const schema = z.object({ planet: z.string() });
// Create your form
const { getFieldState, register, key } = useForm({ schema });
// Get the state of the 'planet' field
const planetState = getFieldState("planet");
</script>
<template>
<div>
<h1>Planet Form</h1>
<input
v-register="register('planet')"
placeholder="Enter your favorite planet"
/>
<p>Planet field State:</p>
<pre>{{ JSON.stringify(planetState, null, 2) }}</pre>
<hr />
</div>
</template>Core API Functions
note: detailed documentation coming soon
useForm(options) – Initializes form state. schema is required; key is recommended on every form so multiple forms on a page don't share state.
v-register – Custom, SSR-safe directive for registering components with Chemical X
register(name: string) – Binds a field to form state.
handleSubmit(onSubmit, onError?) – Builds a submit handler that runs validation and dispatches to your callback. Bind it to @submit.prevent directly:
<script setup lang="ts">
const { handleSubmit } = useForm({ schema, key: 'signup' })
const onSubmit = handleSubmit(async (values) => {
await api.post('/signup', values)
})
</script>
<template>
<form @submit.prevent="onSubmit">...</form>
</template>You can also call the returned handler programmatically: await onSubmit().
getValue(name: string) – Retrieves a field value.
setValue(name: string, value: any) – Updates a field programmatically.
getFieldState(name: string) – Returns field state (value, touched, errors, etc.).
fieldErrors – Reactive Record<path, ValidationError[]>. Auto-populated by handleSubmit on validation failure and cleared on success.
setFieldErrors(errors) / addFieldErrors(errors) – Replace or merge errors imperatively.
clearFieldErrors(path?) – Clear one path or every path.
setFieldErrorsFromApi(payload) – Map a server error envelope ({ error: { details: { path: [msg] } } } or a raw Record<path, string|string[]>) into ValidationError[] and populate the store. Returns the produced errors.
Per-field error display
<script setup lang="ts">
import { z } from 'zod'
const { register, fieldErrors, handleSubmit, setFieldErrorsFromApi } = useForm({
schema: z.object({ email: z.string().email() }),
key: 'signup',
})
const onSubmit = handleSubmit(async (values) => {
// server-side hydration after client validation passed:
try {
await $fetch('/api/signup', { method: 'POST', body: values })
} catch (err) {
if (err.statusCode === 422) setFieldErrorsFromApi(err.data)
}
})
</script>
<template>
<form @submit.prevent="onSubmit">
<input v-register="register('email')" />
<small v-if="fieldErrors.email?.[0]">{{ fieldErrors.email[0].message }}</small>
<button>Submit</button>
</form>
</template>-
Fully SSR Safe – Fully Nuxt 3-compatible with hydration-safe bindings.
-
Validation Handling – Displays schema validation errors automatically.
-
Performance Optimizations – Efficient reactive updates for optimal performance.
@chemical-x/forms is released under the MIT License. See the LICENSE file for details.