WForm 组件
表单容器组件,基于 WinDesignNext WForm 封装,用于包裹 WFormItem 和 WInput 等表单相关组件。支持通过 rules 定义校验规则,配合 WFormItem 的 prop 实现表单验证。
WForm 会自动注册实例到 processor(formId 为组件的 id),可通过 processor.getFormInstance(formId) 获取表单实例,在外部事件处理中调用 validate() 和 resetFields() 方法。
基础用法
下面的示例演示了一个带验证的表单:输入框和下拉选择均设为必填(rules + prop)。点击提交按钮时,在外部事件处理中通过 processor.getFormInstance() 获取表单实例并调用 validate() 方法校验;点击重置按钮时调用 resetFields() 方法重置表单。
两种事件处理方式
WForm 本身不产生事件,事件由表单内的 WInput 和 WButton 触发。支持两种事件监听方式:
方式一:window.addEventListener
通过监听 win-design-a2ui-event 窗口事件。detail 中提供了 getFormInstance 方法:
typescript
window.addEventListener('win-design-a2ui-event', async (e) => {
const { message, respond, getFormInstance } = e.detail;
if (message.userAction.name === 'onSubmit') {
// 通过 detail 中的 getFormInstance 获取表单实例
const formInstance = getFormInstance('form_001');
if (formInstance) {
const valid = await formInstance.validate();
if (!valid) {
respond([]); // 校验不通过,返回空消息
return;
}
}
// 校验通过,继续处理提交逻辑...
respond([]);
}
if (message.userAction.name === 'onReset') {
const formInstance = getFormInstance('form_001');
if (formInstance) {
formInstance.resetFields();
}
respond([]);
}
});
window事件监听中,使用respond代替event.resolve,使用getFormInstance代替processor.getFormInstance。detail中还提供了updateDataModel、updateComponentProp等方法。
方式二:processor.onEvent
通过 processor.onEvent() 注册事件回调,适用于 Vue 应用内部:
typescript
processor.onEvent(async (event) => {
const eventName = event.message.userAction?.name;
if (eventName === 'onSubmit') {
const formInstance = processor.getFormInstance('form_001');
if (formInstance) {
const valid = await formInstance.validate();
if (!valid) {
event.resolve([]);
return;
}
}
// 校验通过,继续处理...
event.resolve([]);
}
});输入事件(WInput)
输入时触发,context 携带当前输入值:
json
{
"action": {
"event": {
"name": "onNameInput",
"context": [
{ "key": "value", "value": { "literalString": "用户输入的值" } }
]
}
}
}提交事件(WButton)
点击提交按钮时,通过 path 从 dataModel 读取最新的输入值,并通过 processor.getFormInstance() 获取表单实例进行校验:
json
{
"action": {
"event": {
"name": "onSubmit",
"context": [
{ "key": "name", "value": { "path": "/name" } },
{ "key": "age", "value": { "path": "/age" } }
]
}
}
}typescript
// 监听提交事件,校验后再处理
processor.onEvent(async (event) => {
const eventName = event.message.userAction?.name;
const context = event.message.userAction?.context;
if (eventName === 'onSubmit') {
// 获取表单实例并校验(formId 为 WForm 的 id)
const formInstance = processor.getFormInstance('form_001');
if (formInstance) {
const valid = await formInstance.validate();
if (!valid) {
event.resolve([]);
return;
}
}
// 校验通过,继续处理提交逻辑
console.log('表单数据:', context);
event.resolve([]);
}
});Props API
WForm
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
id | string | - | 组件唯一标识(必填) |
component | string | WForm | 组件类型(必填) |
size | string | '' | 表单尺寸 |
disabled | boolean | false | 是否禁用所有表单项 |
labelPosition | string | right | 标签位置 |
labelWidth | string | '' | 标签宽度 |
labelSuffix | string | '' | 标签后缀 |
inline | boolean | false | 是否行内表单 |
inlineMessage | boolean | false | 是否行内显示校验信息 |
statusIcon | boolean | false | 是否显示校验状态图标 |
showMessage | boolean | true | 是否显示校验信息 |
validateOnRuleChange | boolean | true | 规则改变时是否立即校验 |
hideRequiredAsterisk | boolean | false | 是否隐藏必填星号 |
rules | object | {} | 表单校验规则 |
children | string[] | - | 子组件 ID 列表(WFormItem) |
WFormItem
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
id | string | - | 组件唯一标识(必填) |
component | string | WFormItem | 组件类型(必填) |
label | string | '' | 标签文本 |
prop | string | - | 对应 model 中的字段名(校验用) |
labelWidth | string | '' | 标签宽度(覆盖 Form 设置) |
contentPosition | string | '' | 内容对齐方式 |
children | string[] | - | 子组件 ID 列表 |
path 支持说明
通用绑定格式见 path 数据绑定速查。
WForm / WFormItem 自身属性不支持 path 绑定,但内部表单控件通过 modelValue.path 与 dataModel 关联:
| 子组件 | path 用法 | 说明 |
|---|---|---|
WInput / WInputNumber 等 | modelValue: { "path": "/field" } | 字段值双向绑定 |
WSelect / WCascader 等 | modelValue + 可选 dataSource | 选中值与动态选项 |
WButton(提交) | action.event.context[].value.path | 提交时读取最新表单值 |
WFormItem.prop 需与 modelValue.path 去掉前导 / 后的字段名一致,以便校验生效。详见下方 三者对应关系。
组件关系
WForm
├── WFormItem (label: "姓名", prop: "name")
│ └── WInput (modelValue.path: "/name")
├── WFormItem (label: "类型", prop: "type")
│ └── WSelect (modelValue.path: "/type")
├── WFormItem (label: "年龄", prop: "age")
│ └── WInput (modelValue.path: "/age")
└── WFormItem
└── WButton (提交)- WForm:表单容器,管理全局表单配置
- WFormItem:表单项容器,绑定标签和校验规则
- WInput:输入框,通过
modelValue.path绑定 dataModel - WSelect:下拉选择,通过
modelValue.path绑定 dataModel 对象;options中value为对象时需配置valueKey - WButton:提交按钮,通过
context中的path读取最新值
表单验证
WForm 支持基于 rules 的表单校验:
- 字段失焦(
blur)或值变化(change)时自动校验 - 提交时通过
processor.getFormInstance(formId).validate()进行全量校验
三者对应关系
表单验证的核心是三个属性值必须保持一致:
WForm rules 的 key → "name" / "type"
WFormItem prop → "name" / "type"
WInput/WSelect modelValue.path → "/name" / "/type" (去掉前导 / 即为字段名)
WForm的model无需手动设置,A2UI 会自动从dataModel构建。
工作流程
用户输入 → WInput 将值同步到 dataModel["name"]
→ 触发 blur/change → WFormItem 根据 rules["name"] 自动校验
用户点击提交按钮
→ 外部事件处理中调用 processor.getFormInstance(formId).validate()
→ 遍历所有 WFormItem 的 rules,逐一校验
→ 全部通过 → 继续处理提交逻辑
→ 存在失败 → 阻止提交,对应字段显示红色错误提示配置步骤
1. 在 WForm 中定义 rules
json
{
"id": "form_001",
"component": "WForm",
"labelWidth": "100px",
"rules": {
"name": [
{ "required": true, "message": "请输入姓名", "trigger": ["blur"] }
],
"age": [
{ "required": true, "message": "请输入年龄", "trigger": ["blur"] },
{ "type": "number", "message": "年龄必须为数字", "trigger": ["blur"] }
]
},
"children": ["form_item_name", "form_item_age", "form_item_submit"]
}2. 在 WFormItem 中设置 prop
prop 的值需要与 rules 中的 key 对应,同时与 dataModel 中的路径名一致:
json
{
"id": "form_item_name",
"component": "WFormItem",
"label": "姓名",
"prop": "name",
"children": ["input_name"]
}3. 外部事件处理中调用校验
json
{
"id": "btn_submit",
"component": "WButton",
"type": "primary",
"action": {
"event": {
"name": "onSubmit",
"context": [
{ "key": "name", "value": { "path": "/name" } },
{ "key": "age", "value": { "path": "/age" } }
]
}
},
"child": "btn_text"
}typescript
processor.onEvent(async (event) => {
if (event.message.userAction?.name === 'onSubmit') {
const formInstance = processor.getFormInstance('form_001');
if (formInstance) {
const valid = await formInstance.validate();
if (!valid) {
event.resolve([]);
return;
}
}
// 校验通过,继续处理提交逻辑...
}
});校验规则(rules)
每条规则支持以下字段(基于 async-validator):
| 字段 | 类型 | 说明 |
|---|---|---|
required | boolean | 是否必填 |
message | string | 校验失败时的提示信息 |
trigger | string[] | 触发校验的方式,如 ["blur", "change"] |
min | number | 最小长度/值 |
max | number | 最大长度/值 |
type | string | 值类型,如 "string"、"number"、"email" |
pattern | RegExp | 正则表达式校验 |
validator | function | 自定义校验函数 |
关于 trigger:
"blur"— 输入框失去焦点时触发校验"change"— 输入框值变化时触发校验- 推荐对必填项使用
["blur"],对格式校验使用["blur", "change"]
常见校验规则示例
json
{
"rules": {
"name": [
{ "required": true, "message": "请输入姓名", "trigger": ["blur"] }
],
"phone": [
{ "required": true, "message": "请输入手机号", "trigger": ["blur"] },
{
"pattern": "/^1[3-9]\\d{9}$/",
"message": "手机号格式不正确",
"trigger": ["blur"]
}
],
"email": [
{ "required": true, "message": "请输入邮箱", "trigger": ["blur"] },
{
"type": "email",
"message": "邮箱格式不正确",
"trigger": ["blur", "change"]
}
],
"age": [
{ "required": true, "message": "请输入年龄", "trigger": ["blur"] },
{
"type": "number",
"min": 0,
"max": 150,
"message": "年龄范围 0-150",
"trigger": ["blur"]
}
]
}
}提交按钮、普通按钮与重置按钮
WButton 点击时触发事件,表单校验/重置在外部事件处理中自行调用:
json
// 提交按钮
{
"id": "btn_submit",
"component": "WButton",
"type": "primary",
"action": { "event": { "name": "onSubmit" } },
"child": "btn_submit_text"
}
// 重置按钮
{
"id": "btn_reset",
"component": "WButton",
"action": { "event": { "name": "onReset" } },
"child": "btn_reset_text"
}外部事件处理:
typescript
processor.onEvent(async (event) => {
const eventName = event.message.userAction?.name;
if (eventName === 'onSubmit') {
// 获取表单实例并校验
const formInstance = processor.getFormInstance('form_001');
if (formInstance) {
const valid = await formInstance.validate();
if (!valid) {
event.resolve([]);
return;
}
}
// 校验通过,继续提交逻辑...
}
if (eventName === 'onReset') {
// 获取表单实例并重置
const formInstance = processor.getFormInstance('form_001');
if (formInstance) {
formInstance.resetFields();
}
event.resolve([]);
}
});
formId为 WForm 的id,WForm 会自动注册实例到processor。