如何在Shadcn-vue的AutoForm中结合Zod Schema设置选择器选项?
如何在Shadcn-vue的AutoForm中结合Zod Schema设置选择器选项?
嘿,刚好我之前也折腾过这个需求,给你一步步拆解怎么实现哈!
首先咱们得明确核心问题:Zod的enum是静态的,没法直接用动态数组,所以得换个思路——用Zod的refine做合法性校验,再给AutoForm的select字段传动态选项。
第一步:准备你的动态账户数据
不管是从接口拉的还是本地模拟的,先把账户数据做成响应式的,比如用ref或者computed:
import { ref } from 'vue'; // 这里可以替换成你从接口获取的异步数据 const accounts = ref([ { id: 'acc_001', name: '我的个人账户' }, { id: 'acc_002', name: '公司运营账户' }, { id: 'acc_003', name: '备用储蓄账户' }, ]);
如果你的账户对象结构不是{value, label}这种select组件默认认的格式,还可以用computed转一下:
import { computed } from 'vue'; const accountOptions = computed(() => { return accounts.value.map(item => ({ value: item.id, // 对应select的value值 label: item.name, // 对应select显示的文本 })); });
第二步:定义带校验的Zod Schema
因为是动态选项,没法用Zod的z.enum(),所以用z.string().refine()来校验提交的值是否在合法选项里:
import { z } from 'zod'; const formSchema = z.object({ accounts: z.string() // 校验值是否存在于账户选项中 .refine( (val) => accountOptions.value.some(opt => opt.value === val), { message: '请选择有效的账户哦' } ) // 可选:给字段加描述,AutoForm会自动用这个当label(也可以后面在fields里单独设) .describe('选择关联账户'), });
第三步:给AutoForm配置select字段
有两种方式把动态选项传给AutoForm:
方式一:用defineField显式配置字段
这种方式更直观,适合需要自定义多个字段属性的场景:
import { defineField } from '@/components/ui/auto-form'; const formFields = [ defineField({ name: 'accounts', // 要和schema里的字段名对应 label: '关联账户', // 可以覆盖schema里的describe内容 component: 'select', // 指定用select组件渲染 props: { options: accountOptions, // 把动态选项传进去 }, }), ];
然后在模板里用AutoForm:
<template> <AutoForm :schema="formSchema" :fields="formFields" @submit="handleFormSubmit" > <button type="submit" class="btn">提交表单</button> </AutoForm> </template> <script setup lang="ts"> const handleFormSubmit = (values: z.infer<typeof formSchema>) => { // 处理表单提交逻辑,比如接口请求 console.log('提交的账户ID:', values.accounts); }; </script>
方式二:在Zod Schema的meta里配置
如果不想单独写fields数组,可以直接在schema的字段上用meta配置组件和选项:
const formSchema = z.object({ accounts: z.string() .refine( (val) => accountOptions.value.some(opt => opt.value === val), { message: '请选择有效的账户哦' } ) .meta({ component: 'select', props: { options: accountOptions, }, }), });
这样模板里的AutoForm只需要传schema就行,不用fields:
<AutoForm :schema="formSchema" @submit="handleFormSubmit"> <button type="submit">提交</button> </AutoForm>
小提示
- 如果账户数据是异步获取的(比如从接口拉),记得用
onMounted去请求,因为是响应式的,数据回来后AutoForm会自动更新选项 - 一定要加
refine校验,不然用户可能提交不在选项里的非法值
内容来源于stack exchange
相关产品推荐
相关产品推荐

