DirectSurface UIDirectSurface UI
开始使用
文档/业务指南

表单开发

import {  RenderFieldPresenter,  RenderFormPanel,  RenderNumberInput,  RenderTextBox,} from 'ds-ui'

表单是业务系统中最常见的页面形态。DirectSurface UI 推荐用 RenderFormPanel 管理字段排列,用 RenderFieldPresenter 管理标签、必填、单位、校验状态和提示信息。

如果你正在搭完整业务页面,先看 常用业务场景组合。本页重点说明表单本身如何组织、绑定和校验。

表单结构

RenderFormPanel
  RenderFieldPresenter
    RenderTextBox / RenderComboBox / RenderDatePicker

RenderFormPanel 负责字段网格,RenderFieldPresenter 负责单个字段的标签和状态,具体输入组件只负责值编辑。

组件选择

字段类型 推荐组件 说明
单行文本 TextField 公共类名是 RenderTextBox。适合姓名、编码、关键字。
多行文本 TextArea 适合备注、批注、说明。
数字 NumberInput 适合年龄、数量、金额、比例。
日期时间 DatePicker 适合日期、时间、日期时间字段。
单选枚举 Dropdown 公共类名是 RenderComboBox。值必须来自候选项。
多选枚举 MultiSelectDropdown 适合标签、诊断集合、权限集合。
树选择 DropTreeEdit 适合科室、分类、层级字典。
表格选择 LookupEdit 适合需要多列候选信息的选择。

最小示例

const form = new RenderFormPanel({  columns: 2,  labelWidth: 88,  adaptive: true,  columnGap: 16,  rowGap: 8,}) form.addField(new RenderFieldPresenter({  label: '姓名',  required: true,  child: new RenderTextBox({ placeholder: '请输入姓名' }),})) form.addField(new RenderFieldPresenter({  label: '年龄',  unit: '岁',  child: new RenderNumberInput({ value: 0 }),}))
LIVE CANVAS可运行组件示例
ON-DEMAND RUNTIME交互式示例将在进入视区时启动避免文档首屏同时初始化多个 Canvas Runtime

字段值管理

表单组件只负责交互和值变化通知,不内置业务表单模型。页面层通常维护一个 draft 对象:

const draft = {  name: '',  age: 0,}const form = new RenderFormPanel({ columns: 2 }) form.addField(new RenderFieldPresenter({  label: '姓名',  required: true,  child: new RenderTextBox({    value: draft.name,    onChange: value => {      draft.name = value    },  }),}))

推荐规则:

  • 输入组件的 value 是 UI 当前值。
  • 页面 draft 是提交前的业务草稿。
  • 服务层 DTO 在提交时由 draft 转换出来。
  • 不要把后端原始对象直接作为多个输入组件共享的可变对象,避免取消编辑时难以回滚。

校验状态

字段校验应该落在字段展示层,而不是只改变输入组件边框。

const nameField = new RenderFieldPresenter({  label: '姓名',  required: true,  status: 'error',  message: '姓名不能为空',  child: new RenderTextBox({ placeholder: '请输入姓名' }),})

这样标签、提示、输入控件可以形成一个完整的校验区域。

校验可以分两类:

类型 时机 展示
即时校验 输入、失焦、选择值变化 更新 RenderFieldPresenterstatusmessage
提交校验 点击保存或提交命令 汇总所有字段错误,并把第一个错误滚动到可视区域。

异步校验要和页面生命周期绑定。页面关闭后返回的异步结果不应继续修改已经释放的字段。

表单提交

表单提交建议分三层:

  • UI 层读取输入控件值。
  • 页面层执行校验、组装请求对象。
  • 服务层提交数据并返回结果。

按钮、菜单、快捷键应尽量绑定页面命令,不要在每个按钮里重复写权限和保存逻辑。

let saving = falseconst saveCommand = {  id: 'form.save',  title: '保存',  canExecute: () => !saving,  execute: () => {    // 校验 draft,然后提交服务  },}

命令状态变化后调用 commandManager.invalidate()。详见 命令与权限

响应式规则

  • 桌面宽度下可以使用 2 到 4 列。
  • 窄宽度下使用 adaptive: true 降低列数。
  • 字段阅读顺序必须稳定,不能因为响应式导致业务语义混乱。
  • 超长标签优先省略号加 tooltip,超长值根据业务决定省略或换行。

使用建议

  • 简单字段用 RenderFormPanel
  • 大量动态字段可以先分组,再在组内使用 FormPanel。
  • 表格内编辑不要嵌完整表单,应使用 GridView 的单元格编辑器。
  • 表单页关闭时清理未完成的异步校验和页面级上下文。

典型组合

查询表单

查询表单通常短而密集,适合放在页面顶部:

PageHeader
RenderFormPanel 查询条件
CommandToolbar 查询 / 重置 / 导出
GridView

查询条件只作为页面 draft。点击查询后再请求数据,不建议每个字段变化都立即刷新大表格。

编辑表单

编辑表单通常需要分组和滚动:

ScrollViewer
  Section 基本信息
    RenderFormPanel
  Section 联系方式
    RenderFormPanel
  Section 备注
    TextArea
Footer CommandToolbar

保存、取消、提交、审核等操作应放在固定操作区或页面命令栏,避免用户滚动到表单底部才看到关键动作。

弹窗表单

弹窗表单适合短字段和临时编辑:

Modal / Popover
  RenderFormPanel
  Confirm / Cancel

弹窗打开时复制 draft,取消时丢弃,确定后把结果交给打开源页面合并。

常见错误

只改输入框边框表示错误

这样标签、必填标识、错误文案和输入框状态会割裂。应把错误状态放到 RenderFieldPresenter

在表格单元格里嵌完整表单

表格编辑应使用 GridView 的编辑能力或单元格 popup 编辑器。完整表单适合页面、抽屉或弹窗。

把页面草稿放到应用级上下文

页面草稿应放在页面对象、页面 controller 或页面级 App Context 中。放到应用级上下文会导致 tab 间串数据和关闭后内存不释放。

相关文档