Valibot 配置表单
用一个 Valibot object schema 同时驱动 Plugin 配置、字段信息和 Web 表单。
给配置字段加标题、说明、控件偏好时,使用 valibot-form metadata。Plugin 仍只声明一份 Valibot schema,
Workbench 会自动显示配置表单;无需为普通配置另外编写 React 页面。
先给一个字段加标题
import { , } from '@pluxel/core'
import * as from 'valibot-form'
import * as from 'valibot'
@()
export class extends {
private readonly = this..(
.({
: .(.(.(), .({ : '启用服务' })), true),
}),
)
}构建并运行插件,标准配置页应出现“启用服务”开关,初始值为开启。
f.formMeta() 只描述显示方式;字段是否必填、默认值和有效范围仍由 Valibot 决定。
保存与运行时应用的区别见插件配置。
最小配置与渲染结果
下面是覆盖多种控件的完整参考例子。按需查找开关、分段选择、URL、整数、嵌套对象和列表; 无需在第一个 Plugin 中一次性采用全部控件。展开预览可直接操作表单,比较原始 Input 与校验后的 Output。
const = .({
: .(
.(
.(),
.({
: '启用示例服务',
: 'schema 默认值会进入 normalized config',
: { : 'runtime', : '运行时' },
}),
),
true,
),
: .(
.(
.(['development', 'production'] as ),
.({ : '运行环境', : 'runtime' }),
.({
: 'segmented',
: { : '开发', : '生产' },
}),
),
'development',
),
: .(
.(
.(),
.(),
.({
: '上游地址',
: 'URL 约束来自 schema;表单只负责编辑。',
: { : 'network', : '网络与重试' },
}),
.({ : 'https://api.example.com' }),
),
'https://api.example.com',
),
: .(
.(
.(),
.(),
.(1),
.(65535),
.({ : '监听端口', : 'network' }),
.({ : 1 }),
),
8787,
),
: .(
.(
.({
: .(
.(
.(),
.(),
.(1),
.(10),
.({ : '最大次数' }),
.({ : 1 }),
),
3,
),
: .(
.(
.(),
.(),
.(100),
.({ : '退避时间(毫秒)' }),
.({ : 100 }),
),
250,
),
}),
.({ : '重试策略', : 'network' }),
.({ : 'card' }),
),
{
: 3,
: 250,
},
),
: .(
.(
.(.(.(), .())),
.({ : '允许的 Origin', : 'network' }),
.({
: 'list',
: 'Origin',
: '添加 Origin',
: 'https://api.example.com',
}),
),
['https://api.example.com'],
),
})
@({ : 'Example' })
export class extends {
private readonly = this..()
override () {
(this.., { : this.. })
}
}配置渲染预览 · 表单、Input 与 Output
当字段既有默认值又有表单 metadata 时,让 v.optional() 包住完成后的 v.pipe():v.optional(v.pipe(base, constraints, metadata), default)。这样默认值属于外层可选语义,字段 extractor 解包 optional 后仍能读取内层 metadata;不要写成 v.pipe(v.optional(base, default), metadata)。
Plugin 的声明和读取时机见配置规则。
metadata 做什么
valibot-form 的 core entry 不依赖 React/Mantine,适合 runtime config、CLI prompt、配置文件编辑器和 schema inspection:
import * as from 'valibot'
import * as from 'valibot-form'
const = .({
: .(
.(['development', 'production'] as ),
.({ : '运行环境' }),
.({
: 'segmented',
: { : '开发', : '生产' },
}),
),
})
const = .()常用映射:
| Valibot schema | metadata | 默认 web 控件 |
|---|---|---|
v.string() | stringMeta | TextInput |
v.number() | numberMeta | NumberInput |
v.boolean() | — | Switch |
v.picklist() | picklistMeta | Select |
v.array() | arrayMeta | List |
v.record() | recordMeta | Table |
v.object() | objectMeta | Card/stack |
v.variant() / union | unionMeta | Select/segmented |
类型入口
类型直接从 package 源码导出。下面的示例由 Twoslash 对当前 workspace 类型检查,不在文档中维护另一份类型声明:
import type { FormMeta, } from 'valibot-form'
import type { } from 'valibot-form/web'
type MetadataKeys = keyof FormMeta
type FormProps = keyof <>formMeta() 的 title / description 使用 Valibot 标准 metadata,help、section、layout、disabled、readOnly 和 hidden
仍是表单展示偏好;类型对应的 *Meta() 只负责控件偏好。requiredness、选项、格式和范围仍来自 Valibot schema,例如
v.optional()、v.url()、v.minValue()、v.maxValue() 和 v.integer()。原生 v.title()、v.description() 与
v.metadata({ title, description }) 也会按 pipe 顺序互操作,但标准示例使用一次 formMeta() 集中声明。
需要编辑 schema 或查看类型补全时,打开独立的配置 Playground。
Web adapter
只有在自己的 React 应用中需要自动表单,才从 valibot-form/web 导入。标准 Workbench 配置页已包含它。
独立应用需要安装 React、Mantine、TanStack Form、Tabler Icons 和 dnd-kit:
npx nypm add valibot-form valibot react react-dom @mantine/core @mantine/hooks @tanstack/react-form @tabler/icons-react @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities
export function () {
return (
<>
<
={}
={{
: { : 'development' },
: async ({ }) => (),
}}
>
<. />
<.>
{({ , , , , }) => (
<>
< ="button" ={() => ()} ={! || }>
重置
</>
< ="button" ={} ={! || }>
保存
</>
</>
)}
</.>
</>
</>
)
}上例是独立 React 应用,因此自行导入 Mantine CSS。放进 Workbench View 时,仍需自己的 MantineProvider,
但应删除 @mantine/core/styles.css 导入,基础 CSS 已由宿主加载;见页面资源参考。
AutoForm 负责根据 schema metadata 规划和渲染字段;配置 authority 仍然是 runtime 的 configs.use() 校验流程。把表单值送回 host API 前,服务端必须再次用同一个 schema 校验,不能把浏览器表单当作信任边界。
嵌套编辑与错误反馈
Object、数组行和当前 Union 分支中的可编辑字段使用完整的 TanStack 字段路径,例如
database.host、servers[0].host。各字段独立记录 blur 和错误;数组删除、重排使用 TanStack 的数组操作,
交互状态随行移动,受影响的校验错误重新校验或清除。
Workbench 的配置保存和 Content action 会把服务端错误放到对应的已显示字段;隐藏字段、未激活分支、 无法准确定位的路径错误保留在表单摘要。编辑字段会清除该字段的旧服务端错误和表单摘要, 其他字段的错误继续显示;开始下一次提交时清除上一轮服务端错误。修改后可保留草稿再次提交。 请求期间继续编辑时,迟到响应不会覆盖新草稿或给新值挂上旧校验错误;配置保存成功仍会更新已保存基线, 新草稿保留为未保存修改。Content action 有新草稿时也不会自动清空或关闭表单;操作反馈仍报告已提交请求的结果。
配置分区保留独立的保存基线与撤销范围;保存当前分区不会清空其他分区的草稿。当前保存和全部保存共享请求流程, 请求结束前不能启动另一笔配置保存,但可以继续编辑。网络失败后保留草稿并允许重试;保存已确认成功时, 后续运行状态刷新失败不会将这笔保存报告为失败。
独立使用 AutoForm 时,
form.setErrorMap({ onServer: { fields: { 'database.host': '地址不可用' } } }) 可设置字段错误;
编辑该字段会清除它的旧服务端错误。跨字段错误与表单摘要的失效策略由调用方决定。
reset() 同时重置表单和局部编辑草稿,包括 Union 的非激活分支缓存、数组与 Record 的新增草稿。
在提交回调中调用 formApi.reset() 具有相同效果。切换字段计划时,使用 resetKey 明确开始新的编辑会话。
formOpts.defaultValues 未提供或为 undefined 时,使用 schema 默认值。控件、context 和重置共享同一次默认值解析结果,
因此动态默认值工厂生成的值也保持一致。AutoForm.Actions 提供的 setValues 按 TanStack 字段路径逐项更新,
例如 setValues({ 'database.host': 'db.example' });它保留其他值,不把带点的 key 当作顶层字面量名称。
Record 内无法被路径准确表示的字面量 key(如 x.y、0 或空字符串)保持原样,通过可绑定的祖先字段编辑;
这类值没有独立的 TanStack 字段路径,Workbench 将相应服务端错误显示在摘要。
如果顶层 key 本身无法被 TanStack 路径准确表示,则显示只读说明并保留原值,避免写入错误位置。
需要编辑这类数据时,将它放在普通命名的 Record 或 Object 字段内。
传入 schema 用于字段规划和默认值,不会自动安装客户端 validator 或将编辑值转换成 schema output。
独立表单可通过 formOpts.validators 显式选择客户端校验时机;Workbench 的 portable 字段计划仍由服务端执行完整校验。
与 Pluxel 配置界面的边界
valibot-form 提供 schema metadata、字段提取和可选 Web adapter,不提供 Pluxel Plugin 发现、配置传输或持久化 API。自定义配置界面应直接接收 browser-safe 的 schema,并通过应用自己的服务端接口提交修改;服务端继续使用同一 schema 校验输入。
Pluxel Workbench 内置的 Plugin 配置页由宿主读取 runtime config metadata。Plugin 作者只声明 this.configs.use(Config),不调用 Workbench 内部的 schema projection 或配置 patch 实现。
最后更新于