Skip to content

FEATURE: 字段插槽自定义组件支持 useCustomFieldValue 把值交给表单 #8381

Description

@zehuichan

Version

Vben Admin V5

Description

字段插槽里的自定义组件如果既没有绑定 componentProps,也没有实现 modelValue(内部用若干控件拼出来的复合组件、第三方组件),表单项拿不到它的值,schema 上的 rules 也就无从校验。

更常见的踩坑是:组件自持一份内部状态、不接收表单下发的值。点「重置」或 setValues 时,表单里的值清了,界面上的选中态还在。antdv 适配器默认把字符串 component 映射成 v-model:value,插槽组件如果用的是标准 modelValue,还要显式写 modelPropName: 'modelValue',否则 props 对不上。

Vant 的 useCustomFieldValue 把这件事收成一套约定:值仍归表单所有,组件只负责 emit 出去;composable 只把取值函数交给外层字段做校验,不自己再存一份。VbenForm 现在没有对等能力。

Proposed Solution

@vben-core/form-ui 增加 useCustomFieldValue,由 form-field provide 字段上下文,组件 inject 后注册取值函数:

<script lang="ts" setup>
import { useCustomFieldValue } from '@vben/common-ui';

const modelValue = defineModel<string[]>({ default: () => [] });

const { disabled, error } = useCustomFieldValue(() => modelValue.value);
</script>
<Form>
  <template #tags="slotProps">
    <TagPicker v-bind="slotProps.componentProps" />
  </template>
</Form>

建议约定:

  • 值仍归表单所有:组件继续用 modelValue 接收表单下发的值(插槽里就是 v-bind="slotProps.componentProps"),setValues、重置才能顺着 props 流回来
  • 取值函数变化时写回字段、清校验,并按 validateOn 触发校验;写回值与表单当前值一致时(重置 / setValues 经组件流回来)不重复写回、也不触发校验,避免一点重置就冒出必填错误
  • 同一个表单项只接受一个取值函数,重复注册忽略并告警
  • 只有完全自持内部状态、不接受外部值的组件,才需要用返回的 value 自行同步
  • schema 里 component 写成字符串、插槽组件用标准 modelValue 时,需要显式 modelPropName: 'modelValue'

已经在 fork 上做了一版,方便对照:

Alternatives Considered

  • 每个自定义组件自己 watch(formApi) / 调 setFieldValue:能用,但每个复合控件都要写一套,口径容易漂。
  • 强制所有字段插槽必须 v-bind="slotProps.componentProps":对单控件够用,复合组件 / 第三方组件的值仍然落不到表单上,rules 还是校验不了。
  • 直接照抄 Vant:Vant 的 composable 只注册 getter、不写回表单。VbenForm 的字段模型需要把值写进 form store 才能走 schema rules,所以写回是必要的;但写回时要跳过「值和表单已经一致」的那一趟,否则重置会立刻触发校验。

Additional Context

实现贴现有能力:form-field provide 字段上下文,取值函数 watch 后走现有 setFieldValue / validateField。不引入新的 schema 字段类型,也不改变提交数据结构。插槽 componentProps.modelValue 在表单值带索引签名、字段类型解析成 unknown 时放宽为 any,否则 v-bind 喂不进声明了具体 model 类型的组件。

Validations

  • Read the docs
  • Ensure the code is up to date. (Some issues have been fixed in the latest version)
  • I have searched the existing issues and checked that my issue does not duplicate any existing issues.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions