跳到主要内容

Form 控件介绍

Form 用于收集、校验和提交一组相关字段。它适合申请、登记、设置、编辑详情和流程步骤,不只是把多个输入框排在一起:Form 还统一管理字段分组、布局、校验状态和提交范围。

阅读本手册后,你可以完成以下配置:

  • 用 Form Section 组织较长的业务表单
  • 配置每行控件数量以及标签和内容的栅格比例
  • 让说明类字段独占整行并保持标签对齐
  • 使用必填、长度、格式和数字范围校验
  • 配置 Reset、Validate 和 Submit 三类操作
  • 只提交当前 Form 的字段,而不是整个页面状态
  • 在 Java 后端识别 DEV / TEST / PROD 和设计预览 / 运行态
  • 配置 Create / Edit / View、条件字段、远程校验和后端字段错误
  • 使用可重复分组、草稿恢复、差量提交和 Schema 生成

1. Form 能力与配置项​

Form 的配置分为四个层级:

  1. Form:管理整个表单的布局、模式、数据加载、提交、草稿和公共状态。
  2. Form Section:按业务主题组织字段,也可以配置为可重复的数据集合。
  3. Field:配置标签、Field Key、默认值、占行方式、条件行为和校验规则。
  4. Button Set / Interaction:通过 Reset、Validate、Submit 和组件函数编排用户操作。

1.1 属性与功能速览​

配置区域主要属性或功能解决的问题
基本结构ID / Name、Form Sections、Fields、Button Set定义表单边界、业务分组和提交范围
布局Controls Per Row、Form column split、Layout、Label Alignment、Full row控制每行字段数量、标签宽度、排列方式和整行字段
模式Create、Edit、View、Warn about unsaved changes区分新建、编辑、只读查看及未保存提醒
数据适配器Load / Create / Update URL、Response Data Path、Record ID、Revision加载记录并连接新增、修改接口和乐观锁
提交Full values、Changed values only、Custom URL决定提交完整表单还是仅提交变化字段
字段校验Required、Length、Pattern、Number、Custom Validator、Remote validation提供即时校验、远程校验和后端字段错误定位
条件字段Visible / Disabled / Required When、Dependencies、Clear When Hidden根据其他字段、Page Context 或当前模式动态调整字段
可重复分组Collection Key、Minimum / Maximum Items、Add / Delete编辑联系人、明细行等对象数组
草稿Browser / Remote storage、Draft Key、Autosave Delay、revision自动保存、恢复或放弃未完成内容
操作与状态reset、validate、submit、saveDraft、restoreDraft、discardDraft;forms.*编排按钮和流程,并读取 valid、dirty、submitting 等状态
字段生成Business Object、JSON Schema、OpenAPI从已有模型快速生成可继续编辑的字段结构

1.2 表单结构与提交边界​

Form 是字段状态和提交范围的边界。一个页面可以放置多个 Form,每个 Form 只管理自己的 Section、Field 和 Button Set:

  • Form Section 用于表达“基本信息、权限、附件”等业务分组,不只是视觉间距。
  • Field Key 是字段在 Form 状态和提交 JSON 中的稳定名称,应与后端 DTO 属性保持一致。
  • Button Set 负责摆放表单操作;按钮是否执行 Reset、Validate 或 Submit,仍由 Interaction 配置决定。
  • Submit Form 只收集目标 Form 已注册的字段,不会自动混入其他 Form、Page Context 或 Tree Current Record。

因此,页面上存在“查询条件”和“编辑详情”两个 Form 时,应分别设置 ID,并让各自按钮明确指向对应 Form。不要依赖字段在页面中的视觉位置推断它属于哪个提交范围。

1.3 布局与响应式​

Form 使用一个共享布局规则控制全部普通字段:

  • Controls Per Row 决定一行最多放置几个字段,也决定每个字段可用的栅格宽度。
  • Form column split 在单个字段区域内分配 Label 和 Content。每行两个控件时两者合计为 12;每行一个控件时合计为 24。
  • Layout 可选择 Horizontal、Vertical 或 Inline;Label Alignment 只控制 Horizontal 标签文字的对齐。
  • 字段的 Full row / Start on new row 让长文本或说明字段独占整行,但标签仍与普通字段的第一列对齐。
  • 窄屏时字段按阅读顺序堆叠,不需要复制一套移动端 Form。

Form 的布局配置控制结构,字段自身只声明是否换行或跨行。这样调整 Controls Per Row 时,普通字段和整行字段会一起重新计算,而不是分别维护互相冲突的宽度。

1.4 Configure Form capabilities 对话框​

选择 Form,在属性面板点击 Configure Form capabilities,会打开一个集中配置 Form 运行态契约的对话框。它把配置按四个页签组织,从上到下就是配置一张业务表单的推荐顺序:

页签解决什么何时配置详见
Lifecycle选择 Create / Edit / View 模式,并开启未保存提醒每个 Form 都要先定模式第 1.4、10 节
Data配置 Data adapter:加载、创建、更新记录的接口与数据格式需要"加载记录 + 保存"完整生命周期时第 14 节
Draft自动保存/恢复尚未提交的内容长表单、跨设备或重要流程第 15 节
Generate fields从 Business Object / JSON Schema / OpenAPI 生成字段从已有模型快速搭表单第 16 节

Lifecycle 页签用同一份表单结构覆盖三种生命周期:

模式页面行为常见接口
Create使用默认值建立新记录Create URL,通常使用 POST
Edit先从 Load URL 加载记录,再提交修改Load URL + Update URL,通常使用 PUT / PATCH
View复用标签和值布局,只读展示Load URL,不显示可编辑操作

开启 Warn about unsaved changes 后,只有相对基线发生变化时才提示离开确认。

Custom URL 还是 Data adapter?​

这是最容易混淆的一点:Data adapter 不是"提交 URL",而是一整套"读 + 写 + 版本控制"的数据接口,和模式配合使用。两者按复杂度二选一:

  • 一次性简单提交(只新建、不需要回填)——直接用 Submit 按钮的 Custom URL 即可,无需配置 Data adapter。
  • 完整生命周期(打开时先加载、区分新建/修改、冲突检测、草稿恢复)——在 Data 页签配置 Data adapter。

Data adapter 的字段各管一件事:

字段适用模式作用
Load URLEdit / View打开页面时 GET 加载记录,回填并作为基线
Create URLCreate新建时 POST 提交
Update URLEdit修改时 PUT / PATCH 提交
Response Data Path加载时从响应 JSON 中取记录的位置,如 data = response.data
Record ID Field加载 / 提交记录主键字段名(如 id)
Revision Field提交乐观锁版本;冲突时后端返回 409,避免覆盖别人的修改
Submission Payload提交提交全量 values,还是仅提交变化字段(Changed values only)

三个 URL 都支持运行态变量:直接写 [[context.params.id]]、[[state.id]]、[[record.id]] 等,或点输入框右侧的 ƒx 按钮从页面变量列表插入,避免把 ID 写死。加载完成后的值会成为 Form 基线:Reset 恢复这个基线,Changed values only 也以它计算差量。

1.5 校验、字段错误与条件行为​

Form 把校验分成三个层次:

  1. 本地规则:Required、Length、Pattern、Number 和 Custom Validator 提供即时反馈。
  2. 远程校验:Remote validation 适合用户名、邮箱、业务编码等需要请求后端判断的字段;可配置触发时机和 Debounce。
  3. 提交校验:后端返回顶层 fieldErrors,Form 按 Field Key 把消息写回具体字段,同时保留整体 displayText。

字段还可以配置 Visible When、Disabled When 和 Required When。表达式读取 state.*、context.*、record.* 或 form.*;Dependencies 明确声明哪些 Field Key 变化时需要重新计算。启用 Clear When Hidden 后,字段隐藏时会清除旧值,避免不可见数据继续提交。

前端校验用于交互反馈,不能替代后端校验、权限和审计。条件隐藏也不是安全控制;敏感字段是否可读写仍应由后端决定。

1.6 可重复分组与草稿​

Form Section 可以变成可重复分组。Section 内的字段作为一行模板,Collection Key 对应提交 JSON 中的对象数组;Minimum / Maximum Items 约束行数,运行态提供 Add / Delete。每行校验错误会保留数组索引,例如 emergencyContacts[0].phone,便于定位具体记录。

草稿用于保存“尚未提交的 Form 状态”,它与正式业务记录不同:

  • Browser storage 适合个人、单设备的短期录入。
  • Remote service 适合跨设备或重要流程,需要配置 Load / Save URL、Draft Key 和 revision。
  • Autosave Delay 控制停止输入多久后保存;远端 revision 冲突必须提示用户恢复或重新加载,不能静默覆盖。

1.7 操作函数与公共状态​

Form 的常用操作可以放在按钮、Step 或其他 Interaction 动作链中:

操作行为
reset恢复加载完成后的基线或创建模式默认值,并清除校验消息
validate校验当前 Form;失败时停止后续动作
submit校验、组装 payload、发送请求并处理后端字段错误
saveDraft / restoreDraft / discardDraft保存、恢复或放弃草稿

页面表达式可以读取 forms.<formId>.valid、dirty、submitting、submitError、lastSubmit 和 mode。例如,Submit 按钮可以在 submitting 时禁用;Step 的 Next 可以先 Submit Form,成功后再执行 nextStep。这些状态由 Form 维护,不应由页面动作直接改写。

1.8 字段生成与后端协作​

Generate fields 可以从 Business Object、JSON Schema 或 OpenAPI Schema 生成 Section 和 Field。生成结果是普通页面元数据,设计人员仍可修改标签、控件类型、选项、布局和校验;生成后必须检查敏感字段、枚举文案、权限和接口配置。

Form 的数据加载、远程校验、草稿和提交请求都会由平台统一携带:

X-Spark-Page-Environment: DEV | TEST | PROD
X-Spark-Page-Render-Mode: DESIGN_PREVIEW | RUNTIME

后端可以在 DESIGN_PREVIEW 返回稳定的调试数据或进入沙箱,在 RUNTIME 执行真实业务流程。环境和渲染模式只用于选择调试策略,不能代替认证、租户隔离和业务授权。

1.9 如何选择配置​

目标建议起点继续阅读
普通新增表单Create + Sections + 本地校验 + Custom URL第 2~8 节基础示例
编辑已有记录Edit + Load / Update URL + Record ID / Revision第 9、10、14 节
只读详情View + Load URL第 10、18 节
动态显示字段Conditions + Dependencies第 11、12 节
联系人或明细行Repeatable Group第 13 节
长时间录入Draft + Warn about unsaved changes第 15 节
从已有模型建表单Generate fields第 16 节
流程步骤中的表单Validate / Submit → Step nextStep第 7、18 节

1.10 Form 中可以使用的字段控件​

先根据数据形状选择字段,再配置布局、校验和 Interaction。下面列出当前组件面板中可直接添加到 Form 的 22 种字段;已隐藏的旧版 Select、MultiSelect 和旧 MultiRowInput 只用于兼容已有页面,不作为新页面的配置入口。

分类字段控件适合的数据
基础输入Input、Address、Text Area单行文字、地址和长文本
选择与人员Select、Radio Button、Checkbox、Switch、Cascade Select、Tree Select、Transfer、User Select、Department Select枚举、层级、集合、用户和部门 ID
日期与数值Date Picker、Time Picker、Calendar、Rate、Slider日期时间、评分、单值或数值范围
编辑器Rich Text、Code Editor、JSON Editor带格式正文、脚本和 JSON
文件与结构化数据Upload、Multi-Row Input文件元数据和对象数组

每个字段页面分别说明适用场景、主要属性、提交值形状、条件与 Interaction。选择控件时以准备提交给后端的数据契约为准,不要只按外观选择。

2. 示例:员工入职申请​

Spark Sample 的 Form 页面演示一份员工入职申请。它包含两个分组、两列布局、一个整行说明字段,以及重置、校验和提交按钮。

页面结构如下:

Screen
└── Form: Employee Onboarding Form
├── Form Section: Employee details
│ ├── Field: Full name
│ ├── Field: Work email
│ ├── Select: Department
│ ├── RadioBox: Employment type
│ └── DatePicker: Start date
├── Form Section: Equipment and access
│ ├── Field: Laptop budget
│ ├── Switch: Administrator access
│ └── TextArea: Request justification
└── Button Set
├── Reset
├── Validate
└── Submit request

示例使用有代表性的初始值,打开页面后即可观察布局与提交行为。真正的业务页面可以清空初始值,或在进入编辑页面时由数据源填充。

3. 添加 Form 与分组​

  1. 打开目标页面并进入 Page Designer。
  2. 把 Form 添加到 Screen、Panel、Grid Column、Tab、Step 或 Content 中。
  3. 选择 Form,在 Form Sections 子元素区域添加一个或多个 Section。
  4. 选择 Section,在 Fields 区域添加 Field、Select、RadioBox、DatePicker、Switch、TextArea 等字段。
  5. 选择 Form 的 Button Set,添加提交和辅助操作按钮。
  6. 为 Form 和字段设置稳定的 ID / Name,保存并检查设计画布和运行态。

分组适合表达业务含义,不建议只为了留白而创建空分组。一个短表单可以只用一个 Section;较长表单可按“基本信息、权限、附件、确认”等主题拆分。

4. 配置布局​

4.1 Controls Per Row​

Controls Per Row 决定 Form 内一行最多放几个普通字段:

值适用场景
1长文本、移动端优先、字段说明较多
2常规 PC 业务表单,推荐起点
3 或 4筛选表单或字段很短的紧凑区域

窄屏下字段会按顺序堆叠,不需要为手机另建一份 Form。

4.2 Form column split​

Form 内部仍使用 24 列栅格,但比例按“单个字段所占区域”计算。Controls Per Row 为 2 时,每个普通字段占 12/24;因此 Label 和 Content 应合计为 12,例如:

Label 4 + Content 8 = 12

Controls Per Row 为 1 时,一个字段占 24,可以使用 6 + 18、7 + 17 等组合。拖动 Form column split 刻度尺时,Label 和 Content 会同步变化,不需要分别填写两个数字。

4.3 独占整行​

选择 TextArea 等需要更大空间的字段,启用 Start on new row / Full row。整行字段的标签仍使用当前 Form 的 Label 比例,与上一行第一个标签对齐;内容区域自动跨越剩余列。

不要为了独占整行把 Controls Per Row 临时改成 1,这会同时改变其他字段。

4.4 Layout 与 Alignment​

属性说明
Horizontal标签和控件在同一行,适合 PC 业务表单
Vertical标签位于控件上方,适合窄容器和长标签
Inline字段和按钮连续排列在同一行,适合搜索条件,不适合长申请表
Label Alignment只影响 Horizontal 下标签文字的左/右对齐

5. 按示例配置字段​

字段控件关键配置
Full nameFieldRequired;Length 2–60
Work emailFieldRequired;Pattern ^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$
DepartmentSelectEngineering、Product、Sales、Operations
Employment typeRadioBoxFull time、Contractor、Intern
Start dateDatePickerFormat YYYY-MM-DD
Laptop budgetNumber FieldRequired;Number range 500–5000;Suffix USD
Administrator accessSwitchDefault Checked 关闭
Request justificationTextAreaFull row;Initial Height 4;Maximum Height 8;Length 20–500

Name / Field Key 是提交 JSON 的属性名。示例最终提交:

{
"fullName": "Avery Chen",
"workEmail": "avery.chen@example.com",
"department": "ENGINEERING",
"employmentType": "FULL_TIME",
"startDate": "2026-09-01",
"laptopBudget": 1800,
"adminAccess": false,
"justification": "Prepare the standard engineering workstation before the employee starts."
}

字段名应与后端 DTO 一致。不要让两个可编辑字段使用同一个 Field Key,否则后写入的值会覆盖前一个。

6. 配置校验​

Form 在提交前会校验当前 Form 的字段。常用规则包括:

  • Required:值不能为空。
  • Length:字符串最短和最长长度。
  • Pattern:用正则表达式检查邮箱、编码等格式。
  • Number:数字最小值和最大值。
  • Custom Validator:表达式无法覆盖的业务规则。

校验失败时,错误显示在对应控件附近,提交动作停止;不要只用 Toast 告诉用户“表单错误”,却不标出具体字段。

前端校验用于即时反馈,后端仍必须保留等价校验。浏览器请求可以绕过,不能把 Required 或 Pattern 当成安全边界。

7. 配置 Reset、Validate 和 Submit​

7.1 Reset​

在 Reset 按钮的 onClick 中添加 Call Component Function:

Component: employee_onboarding_form
Function: reset
Parameters: none

Reset 把字段恢复到初始值,并清除校验提示。它不是把所有字段强制清空。

7.2 Validate​

在 Validate 按钮的 onClick 中添加 Validate Form,Form 选择 employee_onboarding_form。校验成功后可以继续显示成功提示或执行下一步;失败时后续动作不会执行。

7.3 Submit​

在 Submit 按钮的 onClick 中添加 Submit Form:

Form: employee_onboarding_form
Submission Mode: Custom URL
URL: /spark/api/sample/form/requests
Method: POST

提交顺序为:

validate current Form
↓
collect current Form fields only
↓
POST JSON to Custom URL
↓
show backend displayText or configured success action

页面中即使存在另一个 Form、Tree Current Record 或 Page Context,Submit 也只发送选中 Form 已注册的字段,不会把整页状态混入请求体。

8. Java 后端示例​

Controller 使用共享请求头常量解析环境和渲染模式,并统一返回 ApiResult<DTO>:

@RestController
@RequestMapping("/spark/api/sample/form/requests")
public class FormRequestController {

private final FormRequestService requestService;

public FormRequestController(FormRequestService requestService) {
this.requestService = requestService;
}

@PostMapping
public ApiResult<FormRequestReceiptDTO> submit(
@RequestBody FormRequestSubmission request,
@RequestHeader(value = "Accept-Language", required = false)
String language,
@RequestHeader(value = SparkPageRequestHeaders.ENVIRONMENT,
required = false) String environment,
@RequestHeader(value = SparkPageRequestHeaders.RENDER_MODE,
required = false) String renderMode) {
Locale locale = SparkApiResultHelper.resolveLocale(language);
SparkPageRequestContext context =
SparkPageRequestHeaders.resolve(environment, renderMode);
return SparkApiResultHelper.success(
locale,
requestService.submit(request, context),
"SPARK-SAMPLE-FORM-0001");
}
}

Service 可以在设计预览中返回可识别但不落库的回执,在运行态执行真实业务流程:

public FormRequestReceiptDTO submit(
FormRequestSubmission request,
SparkPageRequestContext context) {
validate(request); // 后端等价校验

boolean preview = context.getRenderMode()
== SparkPageRenderMode.DESIGN_PREVIEW;
if (preview) {
return previewReceipt(request, context);
}
return onboardingUseCase.submit(request, context.getEnvironment());
}

平台自动携带:

X-Spark-Page-Environment: DEV | TEST | PROD
X-Spark-Page-Render-Mode: DESIGN_PREVIEW | RUNTIME

Data Source 或 Interaction 中不需要手工重复配置这些 Header。完整协议见页面请求上下文与后端调试。

9. 进阶示例:员工资料编辑​

第二个示例在基础提交之上加入完整的编辑生命周期:页面打开后从后端加载记录,邮箱离开焦点时执行远程校验,管理员权限说明按条件显示,紧急联系人可以增删,修改会自动保存草稿,最终只提交变化过的字段。

对应的可复现页面定义位于 spark-sample/src/main/resources/samples/form-capabilities-page.json,后端位于 FormCapabilityController 和 FormCapabilitySampleService。读者不需要访问 Spark Sample 应用,按下面配置即可重建。

10. 模式和公共状态​

选择 Form,打开 Form capabilities → Lifecycle 页签:

配置行为
Create使用默认值创建记录,提交到 Create URL
Edit从 Load URL 读取记录,提交到 Update URL
View使用相同布局只读显示,不渲染可编辑控件
Warn about unsaved changes离开已修改页面前要求确认

每个 Form 暴露只读状态,可用于表达式、按钮提示或后续动作:

forms.employee_profile_form.valid
forms.employee_profile_form.dirty
forms.employee_profile_form.submitting
forms.employee_profile_form.submitError
forms.employee_profile_form.lastSubmit
forms.employee_profile_form.mode

Form 内部交互也可以用 form.dirty、form.submitting 读取当前 Form。不要直接修改这些状态;它们由字段变化、校验、提交和草稿操作共同维护。

11. 条件字段和依赖​

示例中的 Access reason 仅在打开 Administrator access 后出现:

Visible When: state.adminAccess === true
Required When: state.adminAccess === true
Dependencies: adminAccess
Clear When Hidden: on

字段支持:

  • Visible When:表达式为 true 时显示。
  • Disabled When:表达式为 true 时禁用。
  • Required When:在固定 Required 之外增加动态必填条件。
  • Dependencies:填写逗号分隔的稳定 Field Key,让依赖字段变化时重新计算。
  • Clear When Hidden:字段因条件隐藏时清空旧值,避免提交不可见的敏感或过期数据。

表达式可读取 state.*、context.*、record.* 和 form.*,例如:

state.country === 'US' && form.mode !== 'VIEW'
context.permissions.canApprove === true

循环依赖会让业务含义难以理解。若 A 控制 B,通常不要再让 B 反向控制 A。

12. 远程校验和后端字段错误​

在 Work email 的 Validators 中添加 Remote validation:

Validation URL: /spark/api/sample/form/validate-email
Method: POST
Debounce: 400
Value Parameter: value
Valid Response Path: data.valid
Message Response Path: data.message
Trigger: blur

请求会携带当前值、Field Key、Form ID 和当前 Form values。新输入会取消旧请求并忽略过期响应,避免慢响应覆盖新结果。后端返回:

{
"success": true,
"data": {
"valid": false,
"message": "This email address is already used by the sample data."
}
}

提交后的业务校验应使用统一的字段错误协议:

{
"success": false,
"code": 400,
"errorCode": "SPARK-SAMPLE-FORM-0008",
"displayText": "请检查表单中标记的字段后重试。",
"fieldErrors": {
"workEmail": ["该邮箱已被样例数据占用。"],
"adminAccessReason": ["请说明需要管理员权限的原因。"]
}
}

运行态会把 fieldErrors 写回对应 Form Item,而不是只显示一个全局 Toast。Java Service 使用 SparkFieldValidationException(Message, fieldErrors) 保持字段消息为 Lattice Message,Controller 边界再按 Accept-Language 转换。

13. 可重复分组​

选择 Form Section,打开 Repeatable Group,配置:

Collection Key: emergencyContacts
Minimum Items: 1
Maximum Items: 3
Add Button Text: Add contact

Section 内的字段成为每一行的模板。运行态提供 Add / Delete,校验路径保留数组索引,提交结果为:

{
"emergencyContacts": [
{
"name": "Jordan Chen",
"relationship": "Family",
"phone": "+1 555 0101"
}
]
}

Collection Key 必须稳定,且不要与同一 Form 中的普通字段重名。View 模式只显示已有记录,不显示 Add / Delete。

14. 数据适配器和差量提交​

在 Form capabilities → Data 页签配置 Data adapter。进阶示例的配置如下:

Load URL: /spark/api/sample/form/records/employee-1001
Create URL: /spark/api/sample/form/records
Update URL: /spark/api/sample/form/records/[[state.id]]
Response Data Path: data
Submission Payload: Changed values only
Record ID Field: id
Revision Field: revision

Edit 模式先读取 data 并建立基线。选择 Changed values only 后,提交使用差量数据:

{
"recordId": "employee-1001",
"revision": 3,
"changes": [
{ "op": "replace", "path": "/department", "value": "PRODUCT" },
{ "op": "replace", "path": "/emergencyContacts", "value": [] }
]
}

Create 模式始终提交完整 values;Edit 模式可以选择完整 values 或 change set。revision 用于后端乐观锁,冲突时返回 HTTP 409,不能静默覆盖其他会话的修改。

15. 草稿自动保存和恢复​

在 Draft 页签开启 Autosave:

存储方式使用场景关键配置
Browser storage个人临时录入、无需跨设备Draft Key、Autosave Delay
Remote service跨设备、多人或重要业务Load URL、Save URL、Draft Key、revision

示例使用:

Storage: Remote service
Draft Key: employee-1001
Load URL: /spark/api/sample/form/drafts/employee-1001
Save URL: /spark/api/sample/form/drafts/employee-1001
Autosave Delay: 1500 ms

Form 还提供 saveDraft、restoreDraft、discardDraft 组件函数,可配置明确的“保存草稿”“恢复”“放弃草稿”按钮。远端草稿必须返回 revision;保存旧 revision 时后端返回 409,页面显示冲突状态,不覆盖新草稿。

16. 从模型或 Schema 生成字段​

选择 Form,在 Form capabilities → Generate fields 中选择:

  • Business Object:选择 Spark Business Object,读取字段类型、必填和选项。
  • JSON Schema:粘贴对象 Schema;string、number、boolean、enum、date 会映射到对应控件。
  • OpenAPI:粘贴文档并填写 #/components/schemas/Employee 等 Schema Path;未填写时使用首个可用对象 Schema。

选择 Append generated groups 或 Replace current fields,点击 Generate,检查生成数量后保存。对象数组会生成 Repeatable Group。生成结果是普通、可编辑的页面元数据;运行态不会执行后端返回的任意组件 JSON 或脚本。

生成后仍需人工检查:字段标题、敏感字段、枚举文案、布局、帮助信息、权限、提交 URL 和后端校验。

17. Java 进阶接口示例​

记录、草稿和远程校验使用同一页面请求上下文:

@PatchMapping("/records/{recordId}")
public ApiResult<FormCapabilityRecordDTO> updateRecord(
@PathVariable String recordId,
@RequestBody FormChangeSetSubmission input,
@RequestHeader(value = "Accept-Language", required = false)
String language,
@RequestHeader(value = SparkPageRequestHeaders.ENVIRONMENT,
required = false) String environment,
@RequestHeader(value = SparkPageRequestHeaders.RENDER_MODE,
required = false) String renderMode) {
Locale locale = SparkApiResultHelper.resolveLocale(language);
SparkPageRequestContext context =
SparkPageRequestHeaders.resolve(environment, renderMode);
return SparkApiResultHelper.success(
locale,
service.update(recordId, input, context),
"SPARK-SAMPLE-FORM-0015");
}

样例 Service 按 Environment + Render Mode 隔离内存数据。DESIGN_PREVIEW 返回明显的 Preview Employee,方便 Test / 设计画布检查;真实项目仍应使用认证后的租户、权限、Repository 和业务 UseCase。

18. 常见场景​

  • 详情页:Mode 设为 View,保留 Form 的标签和值布局。
  • 新建页:Mode 设为 Create,配置 Create URL,由后端生成业务 ID。
  • 编辑页:Mode 设为 Edit,配置 Load / Update URL 和 revision。
  • 流程步骤:每个 Step 使用独立 Form;Validate 或 Submit 失败会中断后续 Next 动作。
  • 筛选条:使用 Inline Form,字段保持少量,按钮放在末尾。
  • 长流程:开启草稿和未保存提醒,不要依赖浏览器页面一直打开。

19. 常见问题​

标签与上一行没有对齐​

先确认 Controls Per Row,再确认 Label + Content 等于每个字段可用列数。两列 Form 推荐 4 + 8;整行字段会沿用 Label 4,并自动跨越剩余内容区域。

修改布局后预览没有变化​

确认当前选择的是 Form 而不是某个字段;保存页面后同时检查设计画布和运行态。若 Form 位于很窄的 Grid Column 中,响应式规则可能已经把字段堆叠成单列。

默认值看得到,但提交仍提示必填​

确认使用当前版本并保存最新页面。Form 的默认值应进入同一个校验和提交状态,不需要先手工修改一次。

Submit 发送了意外字段​

检查 Submit Form 的 Form 目标和各字段的 Field Key。正确行为是只收集目标 Form 的已注册字段;Page Context 和其他 Form 不应进入请求体。

设计预览不应真正创建记录​

后端读取 X-Spark-Page-Render-Mode。DESIGN_PREVIEW 返回稳定的预览回执或进入沙箱;RUNTIME 才执行真实写入,同时仍要完成认证、授权与审计。

条件字段没有重新计算​

检查 Dependencies 是否填写了被依赖字段的 Field Key,例如 adminAccess;表达式读取的是 state.adminAccess,不是字段 Display Name。

后端错误只显示在顶部​

确认响应使用顶层 fieldErrors,键与 Form Field Key 完全一致。普通 message / displayText 只能表达整体错误,无法定位字段。

草稿反复提示冲突​

远端保存成功后必须返回新的 revision;下一次保存要带回该 revision。若服务端已经有草稿,而客户端没有 revision,应先 Load / Restore,不要直接覆盖。