Typed CRUD form lifecycle for Vue 2.7 and Vue 3. Keep the existing Element Plus, element-ui, Naive UI, or Ant Design Vue Form; one typed form instance owns create/edit/detail, validation, API errors, reset baselines, linkage, and dynamic rows.
Live examples · Guide · API · Discussions
vformjs is designed for admin projects with many CRUD forms. It fits well if you have:
- 20+ forms, mostly create/edit dialogs
- Repeated create/edit mode switching logic
- Cancel flows that reset to baseline state
- Server-side field-level errors mapped back to inputs
- Dynamic arrays or conditional fields
vformjs can reduce form lifecycle boilerplate by ~20-25% in such projects.
If your project has fewer than 10 forms or they're mostly single-mode (login, settings), a 20-line project-local helper is likely sufficient. Honest positioning helps you choose correctly.
pnpm add @vformjs/element-plus element-plus vue # Vue 3
# pnpm add @vformjs/element-ui element-ui vue@^2.7 # Vue 2.7
# pnpm add @vformjs/naive-ui naive-ui vue
# pnpm add @vformjs/ant-design-vue ant-design-vue vue| Package | Role |
|---|---|
@vformjs/element-plus |
Vue 3 + Element Plus — start here |
@vformjs/element-ui |
Vue 2.7 + element-ui |
@vformjs/naive-ui |
Vue 3 + Naive UI |
@vformjs/ant-design-vue |
Vue 3 + Ant Design Vue |
@vformjs/vue |
useForm / defineAdapter for custom UI |
@vformjs/zod |
Zod schema bridge |
@vformjs/core |
Headless engine (transitive) |
Every Element Plus form uses the same useElForm hook. Template bindings stay
native; lifecycle and advanced script operations share one flat form object.
import { r, useElForm } from '@vformjs/element-plus'
const form = useElForm({
defaults: { name: '', email: '' },
rules: {
name: [r.required(), r.min(2)],
email: [r.required(), r.email()],
},
onSubmit: values => api.save(values),
})<template>
<el-form v-bind="form.host" label-width="100px">
<el-form-item label="Name" prop="name">
<el-input v-model="form.model.name" />
</el-form-item>
<el-form-item label="Email" prop="email">
<el-input v-model="form.model.email" />
</el-form-item>
<el-button type="primary" :loading="form.submitting" @click="form.submit()">
Submit
</el-button>
</el-form>
</template>form.host is { ref, model, rules }; host-native prop is enough when the
host owns validation. defaults infers form.model and onSubmit(values).
Less common capabilities stay on the same object: form.get(), form.list(),
form.validate(), and form.snapshotDraft().
- Modes —
form.load('create' | 'edit' | 'detail', values?)in the dialog/page, not the list - Trust state — reactive
errors,dirty,changedPaths, and server-error scrolling - Submit failures — typed
submitErrorvalues with optional field errors - Rules — static and conditional rules share one
rulesmap - Conditional fields — top-level
when; render withform.hidden(path) - Linkage and options — top-level
linkageandoptions - Dynamic rows —
form.list()with stable keys - Zod —
useZodForm({ schema, defaults })from@vformjs/element-plus/zod - Adapters — swap UI without rewriting form logic
| Link | Content |
|---|---|
| Live examples | Real Element Plus CRUD, conditional linkage, and dynamic array + Zod flows |
| Guide | Install, bind the host Form, modes, rules, arrays, Zod, adapters |
| Migrate existing forms | See how regular CRUD, dynamic fields, large models, and multi-section forms adopt one typed lifecycle |
| Vue 2.7 → Vue 3 | Stable form contracts, safe codemod scope, dry-run, and manual review report |
| API | Options, return types, r.*, linkage, and adapter contracts |
| Integration feedback | Report a completed or blocked real-project adoption |
pnpm dlx vformjs init
pnpm dlx vformjs add form profile
pnpm dlx vformjs audit forms --json
pnpm dlx vformjs doctor
pnpm dlx vformjs migrate vue2-to-vue3 --dry-run --json
pnpm dlx vformjs skill installHost and Zod detection come from package.json. Generated modules use form.host, form.item(path), typed paths, localized rules, and typed submit outcomes; Zod imports only the /zod subpath. Output is idempotent, and edited files are never replaced without --force. Use --dry-run --json in coding-agent loops.
Private/company UI packages are never auto-detected. Configure their generated
import and factory explicitly with --adapter-package and --form-factory;
runtime integration remains a business-owned defineAdapter wrapper.
pnpm install
pnpm test
pnpm docs:dev # product site + docs
pnpm docs:build
pnpm dev:vue3 # Element Plus playground
pnpm dev:vue2
pnpm dev:naive
pnpm dev:antd