You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 13:33:14