NocoBase 子表单字段:用嵌套表单维护一对多关系数据
【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase
本篇围绕 NocoBase 界面搭建中的「子表单」(SubForm,源码中的AssociationField.Nester)字段展开:先说明它适用于哪类关系数据场景、与数据选择器/下拉选择器的区别,再结合仓库中Nester组件的源码实现,讲清对多/对一两种关系字段下子表单的渲染结构、增删行与"随主表一起提交"的底层机制,以及如何通过字段组件切换与联动规则完成完整的嵌套表单配置。
一、子表单是什么:先新建、后关联的嵌套录入
子表单适用于先新建关系数据后关联数据的场景:多层级的关系数据以嵌套表单的形式在同一页面内清晰展示。与数据选择器(Picker)、下拉选择器(Select)等"选已有记录"的关系字段组件相比,子表单的核心差异在于:
- 在当前页面区块上直接维护关系表的字段,而不是跳转或弹窗去挑选一条已存在的记录;
- 关系数据随主表一起提交,一次保存完成主表记录与新增关系记录的落库,免去"先建子记录、再回主表选择关联"的两步操作。
从源码结构看,这一"嵌套"能力由 Formily 的ArrayField承载:对多关系的子表单字段值是一个数组,数组中每一项就是一个"新记录"对象,整棵子表单树最终作为主表表单值的一部分一起提交。
二、两种关系字段下的子表单形态
关系字段类型决定了子表单的形态,Nester.tsx 中的Nester组件会根据字段选项中的关系类型分派到两个不同实现:
hasOne / belongsTo → ToOneNester hasMany / belongsToMany / belongsToArray → ToManyNester即Nester组件内部通过options.type判断,把ToOneNester或ToManyNester包在FlagProvider isInSubForm中渲染(见 Nester.tsx#L59-L76)。
对多关系字段的子表单
ToManyNester是对多场景的主体实现(Nester.tsx#L130-L411),其核心行为可以从源码中逐一对应到界面上的交互:
- 新增一行:
field.value为空时,界面显示"新增"按钮;点击后向表单数组中push(markRecordAsNew({})),把一个标记为"新记录"的空对象压入数组,随后渲染出一组空的嵌套字段供填写。markRecordAsNew用于让提交逻辑区分"需新建的关系记录"与"仅引用已有记录的关联"(Nester.tsx#L389-L406)。 - 编辑已有行:每一行数据被包在
RecordProvider、RecordIndexProvider、DefaultValueProvider中,通过NocoBaseRecursionField递归渲染字段树,basePath指向field.address.concat(index),使每一行的字段值精确落在数组的对应下标上(Nester.tsx#L292-L307)。 - 删除一行:每行右上角的删除按钮通过 Formily 的
spliceArrayState同步更新字段状态,并从field.value与field.initialValue中移除该下标,保证变更能被表单正确识别为"已修改"(Nester.tsx#L271-L290)。是否允许删除受allowDissociate控制:不允许解关联时,只有"尚未保存的新行"(无targetKey)才显示删除按钮;同时带模板的行(x-template-uid)的首行也不允许删除。 - 选择已有记录并入表单:当
allowSelectExistingRecord为真时,额外提供"选择记录"入口,打开一个基于RecordPickerProvider的抽屉选择器;选择结果经usePickActionProps同样以markRecordAsNew标记后并入field.value。从源码结构看,这一机制让子表单既可以"全新建",也可以把已有记录纳入本次提交统一处理。 - 移动端适配:移动端布局下会用
transformMultiColumnToSingleColumn把多列表单的 schema 转成单列再渲染,保证窄屏下的嵌套表单可用性(Nester.tsx#L147-L154)。
组件受allowMultiple、allowDissociate、allowSelectExistingRecord等关联字段选项约束,这些选项来自关系字段本身的配置(如"允许多选""允许解关联"等)。
对一关系字段的子表单
ToOneNester更简洁:关系字段只能有一个值,不展示"新增/删除"行操作,而是直接渲染一个Card包裹的嵌套字段区(Nester.tsx#L117-L127)。值得注意的是源码中的默认值策略:hasOne/belongsTo字段在编辑状态(formBlockType === 'update')下不允许设置默认值,因为其值唯一、不存在"新增值"的语义;而Picker/Select之外的组件模式同样不允许设置默认值(Nester.tsx#L93-L113)。
支持多层关系字段的嵌套配置
子表单内部的关系字段可以继续配置为子表单,从而形成多层嵌套:每一层都由NocoBaseRecursionField递归渲染子 schema 实现,只要内层关系字段同样选择"子表单"组件,即可在页面上逐级展开录入多级关系数据。
三、字段配置项:切换组件与联动规则
在界面搭建的字段配置面板中,子表单字段提供两类关键配置:
字段组件
可切换为其他关系字段组件,例如下拉选择(Select)、数据选择器(Picker)等。这一切换由AssociationField的"模式"(mode)机制统一实现:每种模式对应注册在 index.ts 中的同名组件(AssociationField.Nester = Nester、AssociationField.Select、AssociationField.Picker等),运行时通过AssociationFieldModeProvider决定渲染哪一种。
对多模式的渲染入口在 InternalNester.tsx:它在界面设计器中把Nester的 schema 通过useInsertSchema('Nester')插入到当前关系字段的字段树中(InternalNester.tsx#L30-L62),并支持showTitle控制是否显示区块标题;schema 插入逻辑封装在 hooks.tsx 的useInsertSchema中。更多组件差异(如服务、过滤参数、label/value 字段名)可参考 关系字段说明。
联动规则
子表单字段支持配置联动规则(联动规则说明):让子表单内部或同页面的其他字段,随主表/上级字段的取值变化而执行显示/隐藏、只读/可编辑、默认值等动作。
其底层绑定逻辑在 useLinkageRulesForSubTableOrSubForm.ts:
isSubFormOrSubTableField沿 schema 父级链向上查找,确认当前字段确实处于子表单/子表格模式(遇到FormV2即停止,避免误伤外层表单);useSubFormValue取到子表单自身的 schema 与表单值,从中读出该子表单配置的联动规则;- 随后
forEachLinkageRule遍历每条规则,把命中当前字段(targetFields包含本字段名)的规则通过bindLinkageRulesToFiled绑定到字段上,并在字段卸载时执行__disposes清理,保证嵌套层级内联动规则的生命周期正确。
四、小结:子表单的适用判断
| 场景 | 推荐组件 | 说明 |
|---|---|---|
| 关系记录是"新建"的,且需随主表一次保存 | 子表单(Nester) | 嵌套录入、随主表一起提交 |
| 关系记录已存在,只需建立引用 | 数据选择器 / 下拉选择 | 通过选择器挑选已有记录 |
| 多级层级数据逐层新建 | 多层子表单嵌套 | 内层关系字段继续选子表单 |
结合 Nester.tsx、InternalNester.tsx 与 useLinkageRulesForSubTableOrSubForm.ts 可以看到,NocoBase 的子表单本质是"以 Formily 数组字段为骨架、以递归 schema 为肉、以联动规则为神经"的嵌套表单机制,这使得"先建关系数据、再关联主表"的录入路径可以在一个页面区块内完成,且多层级关系数据的结构与提交逻辑均由同一套递归渲染机制保证一致。
【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考