Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/dev-toolbelt-form-handling
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: design
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/form-handling
What's inside
- Skill name
form-handling- Description
- Form design — state, validation, error feedback. Framework-agnostic.
- License
- MIT
- Instructions
- 100 lines in SKILL.md · view on GitHub
Files (1)
- SKILL.md
SKILL.md (first lines)
# Form Handling
## Detect the Project's Form Library
Before writing any form code, check for an existing library:
| Signal | Library |
|---|---|
| `react-hook-form`, `useForm`, `register`, `Controller` | React Hook Form |
| `formik`, `useFormik`, `<Formik>` | Formik |
| `vee-validate`, `useField`, `useForm` (Vue) | VeeValidate |
| `@angular/forms`, `FormBuilder`, `FormGroup`, `ReactiveFormsModule` | Angular Reactive Forms |
| `zod`, `yup`, `valibot` imports alongside form code | Schema validation library |
If no library is detected: `useState` per field is acceptable for forms with 1–3 fields. For anything larger, recommend adopting the project's preferred library before building.
---
## Core Rules
### Controlled inputs by default
Always bind input value to state and update state on change. Uncontrolled inputs (`ref`-only) are acceptable only for file inputs or third-party widgets that require direct DOM access.
### Validation placement
| Trigger | When to use |
|---|---|
| `onBlur` | Default for most fields — validates after the user leaves the field |
| `onChange` | Use only after the first submission attempt, or for fields with instant feedback (password strength) |
| `onSubmit` | Always run a full validation pass on submit, regardless of field-level validation |
Never validate `onChange` from the first keystroke on empty fields — it creates errors before the user has had a chance to type.
### Schema-first validation
Define validation rules in a single schema (Zod, Yup, Valibot, or equivalent) rather than scattered `if` statements in handlers. The schema is the single source of truth for what constitutes valid data.
```ts
// good — rules live in one place, reusable on the server too
const orderSchema = z.object({
quantity: z.number().min(1).max(999),
email: z.string().email(),
})
```
### Error messages
- One error message per field, displayed below the field it belongs to
- Link the message to the input via `aria-describedby` (the field's `id` matches the error element's `id`)
- Use plain language: "Enter a valid email address", not "Invalid format"
- Clear the error as soon as the field becomes valid again
### Submit state
- Disable the submit button while the form is submitting (see `double-submission prevention` in the agent)
- Show a loading indicator during async submission
- On success: clear the form or navigate away — never leave a successfully submitted form in a dirty state
- On error: surface the server error near the form (not just in a toast), keep field values intact
### Reset and dirty tracking
- Track whether the form is dirty (has unsaved changes) to warn the user before navigation
- `reset()` must restore every field to its initial value, not just clear them to empty
---
## Library-Specific Notes
### React Hook Form
- Prefer `register` over `Controller` for native inputs — less overhead
- Use `Controller` for third-party components (date pickers, select libraries)
- Set `mode: 'onBlur'` as the default validation trigger
- Use `resolver` (zod, yup) to keep validation out of the component
### Formik
- Use `validationSchema` with Yup rather than the `validate` function for complex forms
- Avoid `setFieldValue` inside `onChange` handlers — use Formik's `handleChange` to avoid double renders
- `enableReinitialize` should be `false` by default; set to `true` only when the form must reflect external data changes
### VeeValidate (Vue)
- Use `defineRule` + `configure` globally for shared rules; use inline `rules` only for one-off cases
- Pair with `zod` via `@vee-validate/zod` for schema-first validation
- `useForm` + `useField` (Composition API) is preferred over the Options API component approach
### Angular Reactive Forms
- Always use `FormBuilder` — never instantiate `FormGroup` / `FormControl` manually
- Validators go in the `FormControl` definition, not in the template
- Use `updateOn: 'blur'` on controls that should validate after focus loss
- `AbstractControl.statusChanges` is the right hook for cross-field dependent validation — avoid manual `valueChanges` hacks
---
## Anti-Patterns
| Anti-Pattern | Problem |
|---|---|
| Validation logic duplicated in component and service | Single source of truth broken; rules drift apart |
| Showing all errors before the user interacts | Hostile UX — validate progressively |
| Resetting only visible fields on submit | Hidden state leaks into the next submission |
| Calling `event.preventDefault()` manually and then forgetting to handle errors | Leaves the form in a broken state on failure |
| Storing form state in a global store | Forms are transient UI state — keep them local |
| `any` type for form values | Defeats the purpose of schema validation |From Dev-Toolbelt/dev-team-agents, MIT.
More from Dev-Toolbelt/dev-team-agents
- 0.623score
design-patterns
Dev-Toolbelt
Design patterns — KISS, YAGNI, DRY, SOLID, GoF, DDD reference.
SkillAFreshness: A★ 7Claude Code +9 - 0.620score
graphql
Dev-Toolbelt
GraphQL — schema, resolvers, N+1/DataLoader, pagination.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
api-design
Dev-Toolbelt
REST/GraphQL design — naming, status codes, pagination, idempotency.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
api-versioning
Dev-Toolbelt
API versioning — compatibility rules and deprecation lifecycle.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
architecture-docs
Dev-Toolbelt
Where architecture documents live, what each contains, and the conformance report format.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
async-jobs
Dev-Toolbelt
Async jobs — idempotency, retry strategy, DLQ, observability.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
i18n
Dev-Toolbelt
i18n/l10n — locale detection, translations, pluralization, RTL.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
component-patterns
Dev-Toolbelt
Component patterns — container/presentational for React/Vue/Angular.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
css-quality
Dev-Toolbelt
CSS quality — specificity, magic numbers, responsive.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
data-fetching-integrity
Dev-Toolbelt
Detect and prevent duplicate/redundant API calls in SPA/SSG frontends — tool-agnostic.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
event-driven
Dev-Toolbelt
Event-driven — sourcing, CQRS, saga, idempotency, schema registry.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
frontend-patterns
Dev-Toolbelt
Frontend patterns — debounce, double-submit prevention, error boundaries.
SkillAFreshness: A★ 7Claude Code +9
Signals
- Stars
- 7
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- Oct 18, 2026 (10 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/Dev-Toolbelt/dev-team-agents
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from Dev-Toolbelt
- 0.623score
design-patterns
Dev-Toolbelt
Design patterns — KISS, YAGNI, DRY, SOLID, GoF, DDD reference.
SkillAFreshness: A★ 7Claude Code +9 - 0.620score
graphql
Dev-Toolbelt
GraphQL — schema, resolvers, N+1/DataLoader, pagination.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
api-design
Dev-Toolbelt
REST/GraphQL design — naming, status codes, pagination, idempotency.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
architecture-docs
Dev-Toolbelt
Where architecture documents live, what each contains, and the conformance report format.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
async-jobs
Dev-Toolbelt
Async jobs — idempotency, retry strategy, DLQ, observability.
SkillAFreshness: A★ 7Claude Code +9 - 0.618score
api-versioning
Dev-Toolbelt
API versioning — compatibility rules and deprecation lifecycle.
SkillAFreshness: A★ 7Claude Code +9
Cite this page
form-handling skill. Agent Mart. https://agentmart.dev/skills/dev-toolbelt-form-handling (last updated 2026-10-24)