A lightweight UI-agnostic schema-driven form engine for Vue 3.
Status: Experimental. This project is currently in 0.x and the API may change.
This project is not a low-code form builder. It is a small form protocol and runtime for complex business forms that need conditional fields, custom widgets, array fields, async validation, hidden payload strategies, and UI adapter rendering.
Use native UI-library forms directly for simple forms.
Use Vue Form Engine when your project has:
- many repeated business forms;
- conditional visibility or disabled rules;
- hidden fields that should not be submitted;
- custom business blocks such as captcha, invitation code, map picker, uploader;
- async validation with debounce;
- dynamic object arrays;
- a need to reuse form behavior across different UI libraries.
packages/core schema protocol, registry, condition, validation, submit utilities
packages/vue Vue renderer and plugin
packages/adapter-antdv Ant Design Vue field adapter
playground runnable demos
import { createApp } from 'vue';
import Antd from 'ant-design-vue';
import { createVueFormEngine } from '@speykye/vue-form-engine';
import { antdvAdapter } from '@speykye/vue-form-engine-adapter-antdv';
const app = createApp(App);
app.use(Antd);
app.use(createVueFormEngine({ plugins: [antdvAdapter()] }));
app.mount('#app');<script setup lang="ts">
import { ref } from 'vue';
import type { FormSchema } from '@speykye/vue-form-engine';
const model = ref({});
const schema: FormSchema = {
hiddenValueStrategy: 'submitVisibleOnly',
sections: [
{
title: 'Account',
items: [
{ key: 'username', type: 'input', label: 'Username', rules: [{ required: true }] },
{
key: 'userType',
type: 'select',
label: 'User Type',
options: [
{ label: 'Normal', value: 'normal' },
{ label: 'Enterprise', value: 'enterprise' }
]
},
{
key: 'companyName',
type: 'input',
label: 'Company Name',
visibleWhen: {
deps: ['userType'],
predicate: model => model.userType === 'enterprise'
}
}
]
}
]
};
</script>
<template>
<DynamicFormEngine v-model="model" :schema="schema" @submit="console.log" />
</template>engine.registerField('captcha', CaptchaField);The field component receives field, modelValue, model, disabled, readonly, errorMessage, and emits update:modelValue, change, blur.
Use blocks when one component controls multiple model keys.
engine.registerBlock('invitationCode', InvitationCodeBlock);{
kind: 'block',
key: 'invitationBlock',
type: 'invitationCode',
props: {
invitationCodeKey: 'invitationCode',
invitationVerifiedKey: 'invitationVerified'
}
}Experimental 0.1.0. The current goal is to validate the protocol, runtime, adapter architecture, and playground demos.
- Stabilize core runtime API
- Improve array field validation
- Add Element Plus adapter
- Add Vant adapter
- Add more declarative condition operators
- Add Zod validation plugin
- Publish 0.1.0 package to npm