Combo 组合

用于将多个表单项组合到一起,实现深层结构的数据编辑。

比如想提交 user.name 这样的数据结构,有两种方法:一种是将表单项的 name 设置为user.name,另一种就是使用 combo。

基本使用

配置items属性,组合多个表单项

```schema: scope=”body” { “type”: “form”, “debug”: true, “api”: “/api/mock2/form/saveForm”, “body”: [ { “type”: “combo”, “name”: “user”, “label”: “用户”, “items”: [ { “name”: “text”, “label”: “名字”, “type”: “input-text” }, { “name”: “gender”, “label”: “性别”, “type”: “select”, “options”: [“男”, “女”] } ] } ] }

  1. ## 多行展示模式
  2. 默认,combo 内表单项是横着展示一排,如果想换行展示,可以配置`"multiLine": true`
  3. ```schema: scope="body"
  4. {
  5. "type": "form",
  6. "mode": "horizontal",
  7. "api": "/api/mock2/form/saveForm",
  8. "body": [
  9. {
  10. "type": "combo",
  11. "name": "combo1",
  12. "label": "Combo 单行展示",
  13. "items": [
  14. {
  15. "name": "text",
  16. "label": "文本",
  17. "type": "input-text"
  18. },
  19. {
  20. "name": "select",
  21. "label": "选项",
  22. "type": "select",
  23. "options": ["a", "b", "c"]
  24. }
  25. ]
  26. },
  27. {
  28. "type": "divider"
  29. },
  30. {
  31. "type": "combo",
  32. "name": "combo2",
  33. "label": "Combo 多行展示",
  34. "multiLine": true,
  35. "items": [
  36. {
  37. "name": "text",
  38. "label": "文本",
  39. "type": "input-text"
  40. },
  41. {
  42. "name": "select",
  43. "label": "选项",
  44. "type": "select",
  45. "options": ["a", "b", "c"]
  46. }
  47. ]
  48. }
  49. ]
  50. }

多选模式

默认,combo 为单选模式,可以配置"multiple": true实现多选模式。

这时提交的将会是对象数组。

```schema: scope=”body” { “type”: “form”, “mode”: “horizontal”, “api”: “/api/mock2/form/saveForm”, “debug”: true, “body”: [ { “type”: “combo”, “name”: “combo1”, “label”: “Combo 单选展示”, “items”: [ { “name”: “text”, “label”: “文本”, “type”: “input-text” }, { “name”: “select”, “label”: “选项”, “type”: “select”, “options”: [“a”, “b”, “c”] } ] }, { “type”: “divider” }, { “type”: “combo”, “name”: “combo2”, “label”: “Combo 多选展示”, “multiple”: true, “items”: [ { “name”: “text”, “label”: “文本”, “type”: “input-text” }, { “name”: “select”, “label”: “选项”, “type”: “select”, “options”: [“a”, “b”, “c”] } ] } ] }

  1. ## 限制个数
  2. 多选模式下,可以配置`minLength``maxLength`配置该 Combo 可添加的条数
  3. ```schema: scope="body"
  4. {
  5. "type": "form",
  6. "mode": "horizontal",
  7. "api": "/api/mock2/form/saveForm",
  8. "body": [
  9. {
  10. "type": "combo",
  11. "name": "combo1",
  12. "label": "最少添加1条",
  13. "multiple": true,
  14. "minLength": 1,
  15. "items": [
  16. {
  17. "name": "text",
  18. "label": "文本",
  19. "type": "input-text"
  20. },
  21. {
  22. "name": "select",
  23. "label": "选项",
  24. "type": "select",
  25. "options": ["a", "b", "c"]
  26. }
  27. ]
  28. },
  29. {
  30. "type": "combo",
  31. "name": "combo2",
  32. "label": "最多添加3条",
  33. "multiple": true,
  34. "maxLength": 3,
  35. "items": [
  36. {
  37. "name": "text",
  38. "label": "文本",
  39. "type": "input-text"
  40. },
  41. {
  42. "name": "select",
  43. "label": "选项",
  44. "type": "select",
  45. "options": ["a", "b", "c"]
  46. }
  47. ]
  48. }
  49. ]
  50. }

值格式

观察下例中表单数据域值的变化,可以发现:

  • 单选模式时,数据格式为对象
  • 多选模式时,数据格式为数组,数组成员是对象

```schema: scope=”body” { “type”: “form”, “debug”: true, “mode”: “horizontal”, “api”: “/api/mock2/form/saveForm”, “body”: [ { “type”: “combo”, “name”: “combo1”, “label”: “Combo 单选展示”, “items”: [ { “name”: “text”, “label”: “文本”, “type”: “input-text” }, { “name”: “select”, “label”: “选项”, “type”: “select”, “options”: [“a”, “b”, “c”] } ] }, { “type”: “divider” }, { “type”: “combo”, “name”: “combo2”, “label”: “Combo 多选展示”, “multiple”: true, “items”: [ { “name”: “text”, “label”: “文本”, “type”: “input-text” }, { “name”: “select”, “label”: “选项”, “type”: “select”, “options”: [“a”, “b”, “c”] } ] } ] }

  1. ### 打平值
  2. 默认多选模式下,数据格式是对象数组的形式,当你配置的组合中只有一个表单项时,可以配置`"flat": true`,将值进行打平处理。
  3. ```schema: scope="body"
  4. {
  5. "type": "form",
  6. "debug": true,
  7. "mode": "horizontal",
  8. "api": "/api/mock2/form/saveForm",
  9. "body": [
  10. {
  11. "type": "combo",
  12. "name": "combo1",
  13. "label": "默认模式",
  14. "multiple": true,
  15. "items": [
  16. {
  17. "name": "text",
  18. "type": "input-text"
  19. }
  20. ]
  21. },
  22. {
  23. "type": "divider"
  24. },
  25. {
  26. "type": "combo",
  27. "name": "combo2",
  28. "label": "打平模式",
  29. "multiple": true,
  30. "flat": true,
  31. "items": [
  32. {
  33. "name": "text",
  34. "type": "input-text"
  35. }
  36. ]
  37. }
  38. ]
  39. }

查看上例表单数据域,可以看到打平后数据格式如下:

  1. {
  2. "combo2": ["aaa", "bbb"]
  3. }

增加层级

combo 还有一个作用是增加层级,比如返回的数据是一个深层对象

  1. {
  2. "a": {
  3. "b": "data"
  4. }
  5. }

如果要用文本框显示,name 必须是 a.b,但使用 combo 创建层级后,name 就可以只是 b

  1. {
  2. "name": "a",
  3. "type": "combo",
  4. "label": "",
  5. "noBorder": true,
  6. "multiLine": true,
  7. "items": [
  8. {
  9. "type": "input-text",
  10. "name": "b"
  11. }
  12. ]
  13. }

这样就能结合 definitions 实现无限层级结构。

唯一验证

可以在配置的body项上,配置"unique": true,指定当前表单项不可重复

```schema: scope=”body” { “type”: “form”, “debug”: true, “mode”: “horizontal”, “api”: “/api/mock2/form/saveForm”, “body”: [ { “type”: “combo”, “name”: “combo666”, “label”: “唯一”, “multiple”: true, “items”: [ { “name”: “text”, “type”: “input-text”, “placeholder”: “文本”, “unique”: true }, { “name”: “select”, “type”: “select”, “options”: [ “a”, “b”, “c” ], “unique”: true } ] } ] }

  1. 上例中,`text``select`都配置了`"unique": true`,新增多条 combo,在任意两个`text`输入框的值相同时,提交时都会报错`"当前值不唯一"`,而`select`选择框也不可选择重复的选项
  2. > 暂不支持 `Nested-Select` 组件
  3. ## 拖拽排序
  4. 多选模式下,可以配置`"draggable": true`实现拖拽调整排序
  5. ```schema: scope="body"
  6. {
  7. "type": "form",
  8. "debug": true,
  9. "mode": "horizontal",
  10. "api": "/api/mock2/form/saveForm",
  11. "body": [
  12. {
  13. "type": "combo",
  14. "name": "combo",
  15. "label": "拖拽排序",
  16. "multiple": true,
  17. "value": [
  18. {
  19. "text": "1",
  20. "select": "a"
  21. },
  22. {
  23. "text": "2",
  24. "select": "b"
  25. }
  26. ],
  27. "draggable": true,
  28. "items": [
  29. {
  30. "name": "text",
  31. "type": "input-text"
  32. },
  33. {
  34. "name": "select",
  35. "type": "select",
  36. "options": [
  37. "a",
  38. "b",
  39. "c"
  40. ]
  41. }
  42. ]
  43. }
  44. ]
  45. }

条件分支

默认 Combo 渲染的成员是固定表单项的,成员的类型时一致,如果不一致怎么办?这里可以设置条件分支来给不同的成员设置不同的表单项。

如下面的例子,定义了两种类型:文本和数字,用户新增的时候可以选择是新增文本还是数字。区分是文字和数字的方式是根据成员数据中的 type 字段来决定。

```schema: scope=”form-item2” { “type”: “combo”, “name”: “combo-conditions2”, “label”: “多选”, “value”: [ { “type”: “text” } ], “multiLine”: true, “multiple”: true, “typeSwitchable”: false, “conditions”: [ { “label”: “文本”, “test”: “this.type === \”text\””, “scaffold”: { “type”: “text”, “label”: “文本”, “name”: “” }, “items”: [ { “label”: “名称”, “name”: “label”, “type”: “input-text” }, { “label”: “字段名”, “name”: “name”, “type”: “input-text” } ] }, { “label”: “数字”, “test”: “this.type === \”number\””, “scaffold”: { “type”: “number”, “label”: “数字”, “name”: “” }, “items”: [ { “label”: “名称”, “name”: “label”, “type”: “input-text” }, { “label”: “字段名”, “name”: “name”, “type”: “input-text” }, { “label”: “最小值”, “name”: “min”, “type”: “input-number” }, { “label”: “最大值”, “name”: “max”, “type”: “input-number” }, { “label”: “步长”, “name”: “step”, “type”: “input-number” } ] } ] }

  1. - `conditions` Array<Condition> 数组,每个成员是一种类型
  2. - `conditions[x].label` 类型名称
  3. - `conditions[x].test` 表达式,目标成员数据是否属于这个类型?
  4. - `conditions[x].scaffold` 初始数据,当新增的时候直接使用此数据。
  5. - `conditions[x].items` 该类型的表单设置。
  6. - `typeSwitchable` 类型是否允许切换,如果设置成 true 会多一个类型切换的按钮。
  7. ## Tabs 模式
  8. 默认成员是一个一个排列的,如果数据比较多有点让人眼花缭乱。所以 Combo 支持了 tabs 的排列方式。
  9. ```schema: scope="form-item2"
  10. {
  11. "type": "combo",
  12. "name": "combo101",
  13. "label": "组合多条多行",
  14. "multiple": true,
  15. "multiLine": true,
  16. "value": [
  17. {}
  18. ],
  19. "tabsMode": true,
  20. "tabsStyle": "card",
  21. "maxLength": 3,
  22. "items": [
  23. {
  24. "name": "a",
  25. "label": "文本",
  26. "type": "input-text",
  27. "placeholder": "文本",
  28. "value": "",
  29. "size": "full"
  30. },
  31. {
  32. "name": "b",
  33. "label": "选项",
  34. "type": "select",
  35. "options": [
  36. "a",
  37. "b",
  38. "c"
  39. ],
  40. "size": "full"
  41. }
  42. ]
  43. }
  • tabsMode boolean 用来开启此模式
  • tabsStyle string 样式,可选:linecard 或者 radio.
  • tabsLabelTpl 用来生成标题的模板,默认为:成员 ${index|plus}

注意:这是新引入的功能,目前还不支持拖拽组合使用。且此模式只有多选时才能生效。

获取父级数据

默认情况下,Combo 内表达项无法获取父级数据域的数据,如下,我们添加 Combo 表单项时,尽管 Combo 内的文本框的name与父级数据域中的super_text变量同名,但是没有自动映射值。

```schema: scope=”body” { “type”: “form”, “debug”: true, “mode”: “horizontal”, “api”: “/api/mock2/form/saveForm”, “body”: [ { “type”: “input-text”, “label”: “父级文本框”, “name”: “super_text”, “value”: “123” }, { “type”: “combo”, “name”: “combo1”, “label”: “不可获取父级数据”, “multiple”: true, “items”: [ { “name”: “super_text”, “type”: “input-text” } ] } ] }

  1. 可以配置`"canAccessSuperData": true`开启此特性,如下,配置了该配置项后,添加 Combo `text`表单项会自动映射父级数据域的同名变量
  2. ```schema: scope="body"
  3. {
  4. "type": "form",
  5. "debug": true,
  6. "mode": "horizontal",
  7. "api": "/api/mock2/form/saveForm",
  8. "body": [
  9. {
  10. "type": "input-text",
  11. "label": "父级文本框",
  12. "name": "super_text",
  13. "value": "123"
  14. },
  15. {
  16. "type": "combo",
  17. "name": "combo2",
  18. "label": "可获取父级数据",
  19. "multiple": true,
  20. "canAccessSuperData": true,
  21. "items": [
  22. {
  23. "name": "super_text",
  24. "type": "input-text"
  25. }
  26. ]
  27. }
  28. ]
  29. }

同步更新内部表单项

配置canAccessSuperData可以获取父级数据域值,但是为了效率,在父级数据域变化的时候,默认 combo 内部是不会进行同步的

如下,添加一组 combo,然后可以看到默认会映射父级变量值123,但是当你在更改父级数据域super_text文本框值后,combo 内部文本框并没有同步更新

```schema: scope=”body” { “type”: “form”, “debug”: true, “mode”: “horizontal”, “api”: “/api/mock2/form/saveForm”, “body”: [ { “type”: “input-text”, “label”: “父级文本框”, “name”: “super_text”, “value”: “123” }, { “type”: “combo”, “name”: “combo2”, “label”: “可获取父级数据”, “multiple”: true, “canAccessSuperData”: true, “items”: [ { “name”: “super_text”, “type”: “input-text” } ] } ] }

  1. 如果想实现内部同步更新,需要如下配置:
  2. - 配置`"strictMode": false`
  3. - 配置`syncFields`字符串数组,数组项是需要同步的变量名
  4. 以上面为例,我们在 combo 上配置`"strictMode": false``"syncFields": ["super_text"]`,即可实现同步
  5. ```schema: scope="body"
  6. {
  7. "type": "form",
  8. "debug": true,
  9. "mode": "horizontal",
  10. "api": "/api/mock2/form/saveForm",
  11. "body": [
  12. {
  13. "type": "input-text",
  14. "label": "父级文本框",
  15. "name": "super_text",
  16. "value": "123"
  17. },
  18. {
  19. "type": "combo",
  20. "name": "combo2",
  21. "label": "可获取父级数据",
  22. "multiple": true,
  23. "canAccessSuperData": true,
  24. "strictMode": false,
  25. "syncFields": ["super_text"],
  26. "items": [
  27. {
  28. "name": "super_text",
  29. "type": "input-text"
  30. }
  31. ]
  32. }
  33. ]
  34. }

设置序号

默认 Combo 数据域中,每一项会有一个隐藏变量index,可以利用 Tpl 组件,显示当前项序号

```schema: scope=”body” { “type”: “form”, “debug”: true, “mode”: “horizontal”, “api”: “/api/mock2/form/saveForm”, “body”: [ { “type”: “combo”, “name”: “combo”, “label”: “显示序号”, “multiple”: true, “items”: [ { “type”: “tpl”, “tpl”: “<%= this.index + 1%>”, “className”: “p-t-xs”, “mode”: “inline” }, { “name”: “text”, “type”: “input-text” } ] } ] }

  1. ## 自定义删除按钮
  2. 默认删除单项按钮为"x",可以通过配置 deleteBtn 属性自定义删除单项按钮,目前 deleteBtn 支持的属性有
  3. `string`和[Button]($docs-zh-CN-components-button.md)类型
  4. 如下,当 deleteBtn `string`时,对应的值会被渲染成文本
  5. ```schema: scope="body"
  6. {
  7. "type": "form",
  8. "debug": true,
  9. "mode": "horizontal",
  10. "api": "/api/mock2/form/saveForm",
  11. "body": [
  12. {
  13. "type": "combo",
  14. "name": "combo",
  15. "label": "删除按钮文本",
  16. "multiple": true,
  17. "deleteBtn": "删除",
  18. "items": [
  19. {
  20. "name": "text",
  21. "type": "input-text"
  22. }
  23. ],
  24. "value": [
  25. {
  26. "text": "1"
  27. }
  28. ]
  29. }
  30. ]
  31. }

如果想要赋予删除按钮更多能力,则需要将 deleteBtn 配置成Button类型

```schema: scope=”body” { “type”: “form”, “debug”: true, “mode”: “horizontal”, “api”: “/api/mock2/form/saveForm”, “body”: [ { “type”: “combo”, “name”: “combo”, “label”: “更复杂的删除按钮”, “multiple”: true, “deleteBtn”: { “type”: “button”, “label”: “delete”, “level”: “danger”, “tooltip”: “提示文本”, “tooltipPlacement”: “top”, “onClick”: “alert(index)” }, “items”: [ { “name”: “text”, “type”: “input-text” } ], “value”: [ { “text”: “1” } ] } ] }

  1. ## 自定义新增按钮
  2. 可以通过配置 `addBtn` 属性自定义新增按钮,在非 Tabs 模式下生效。目前 `addBtn` 支持属性 [Button]($docs-zh-CN-components-button.md)类型
  3. 如果仅想更改新增按钮文本请使用 `addButtonText`, 仅想增添样式请使用 `addButtonClassName`
  4. ```schema: scope="body"
  5. {
  6. "type": "form",
  7. "debug": true,
  8. "mode": "horizontal",
  9. "api": "/api/mock2/form/saveForm",
  10. "body": [
  11. {
  12. "type": "combo",
  13. "name": "combo",
  14. "label": "自定义新增",
  15. "multiple": true,
  16. "addBtn": {
  17. "type": "button",
  18. "label": "增加",
  19. "level": "default",
  20. "block": true
  21. },
  22. "items": [
  23. {
  24. "name": "text",
  25. "type": "input-text"
  26. }
  27. ],
  28. "value": [
  29. {
  30. "text": ""
  31. }
  32. ]
  33. }
  34. ]
  35. }

属性表

当做选择器表单项使用时,除了支持 普通表单项属性表 中的配置以外,还支持下面一些配置

属性名 类型 默认值 说明
formClassName string 单组表单项的类名
items Array<表单项> 组合展示的表单项
items[x].columnClassName string 列的类名,可以用它配置列宽度。默认平均分配。
items[x].unique boolean 设置当前列值是否唯一,即不允许重复选择。
noBorder boolean false 单组表单项是否显示边框
scaffold object {} 单组表单项初始值
multiple boolean false 是否多选
multiLine boolean false 默认是横着展示一排,设置以后竖着展示
minLength number 最少添加的条数
maxLength number 最多添加的条数
flat boolean false 是否将结果扁平化(去掉 name),只有当 items 的 length 为 1 且 multiple 为 true 的时候才有效。
joinValues boolean true 默认为 true 当扁平化开启的时候,是否用分隔符的形式发送给后端,否则采用 array 的方式。
delimiter string false 当扁平化开启并且 joinValues 为 true 时,用什么分隔符。
addable boolean false 是否可新增
removable boolean false 是否可删除
deleteApi API 如果配置了,则删除前会发送一个 api,请求成功才完成删除
deleteConfirmText string "确认要删除?" 当配置 deleteApi 才生效!删除时用来做用户确认
draggable boolean false 是否可以拖动排序, 需要注意的是当启用拖动排序的时候,会多一个\$id 字段
draggableTip string "可通过拖动每行中的【交换】按钮进行顺序调整" 可拖拽的提示文字
subFormMode string "normal" 可选normalhorizontalinline
placeholder string `` 没有成员时显示。
canAccessSuperData boolean false 指定是否可以自动获取上层的数据并映射到表单项上
conditions object 数组的形式包含所有条件的渲染类型,单个数组内的test 为判断条件,数组内的items为符合该条件后渲染的schema
typeSwitchable boolean false 是否可切换条件,配合conditions使用
strictMode boolean true 默认为严格模式,设置为 false 时,当其他表单项更新是,里面的表单项也可以及时获取,否则不会。
syncFields Array<string> [] 配置同步字段。只有 strictModefalse 时有效。如果 Combo 层级比较深,底层的获取外层的数据可能不同步。但是给 combo 配置这个属性就能同步下来。输入格式:["os"]
nullable boolean false 允许为空,如果子表单项里面配置验证器,且又是单条模式。可以允许用户选择清空(不填)。
itemClassName string 单组 CSS 类
itemsWrapperClassName string 组合区域 CSS 类
deleteBtn Button or string 自定义删除按钮 只有当removabletrue 时有效; 如果为string则为按钮的文本;如果为Button则根据配置渲染删除按钮。
addBtn Button 自定义新增按钮 可新增自定义配置渲染新增按钮,在tabsMode: true下不生效。
addButtonClassName string 新增按钮 CSS 类名
addButtonText string "新增" 新增按钮文字

事件表

当前组件会对外派发以下事件,可以通过onEvent来监听这些事件,并通过actions来配置执行的动作,在actions中可以通过event.data.xxx事件参数变量来获取事件产生的数据,详细请查看事件动作

事件名称 事件参数 说明
add `event.data.value: string \ string[]` 当前数据集 添加组合项时触发
delete event.data.key: number 移除项的索引
`event.data.value: string \
string[]` 现有的数据集 删除组合项时触发
tabsChange event.data.key: number 选项卡索引 当设置 tabsMode 为 true 时,切换选项卡时触发

动作表

当前组件对外暴露以下特性动作,其他组件可以通过指定actionType: 动作名称componentId: 该组件id来触发这些动作,动作配置可以通过args: {动作配置项名称: xxx}来配置具体的参数,详细请查看事件动作

动作名称 动作配置 说明
clear - 清空
reset - 将值重置为resetValue,若没有配置resetValue,则清空
setValue `value: object \ Array更新的值<br/>index?: number` 指定更新的数据索引, 1.10.1 及以上版本引入 更新数据,对象数组针对开启multiple模式, multiple模式下可以通过指定index来更新指定索引的数据

动作示例

复制数值

1.10.1 及以上版本

此示例主要用来演示如何通过已有数据快速填充 combo 某条数据。点击 copy 按钮会弹出一个 crud 列表,点击对应行上的复制按钮,将选中数据填充到外层的 combo.

注意事项:

  1. 需要给 combo 设置个 id 属性,用来给事件动作指定目标用。
  2. 弹窗按钮配置了数据映射 {comboIndex: "${index}"} 因为 crud 的行数据上也有 index 变量,派送动作时获取 index 变量是 crud 所在行的序号。所以弹出弹窗的时候,先把 combo 的序号赋值给 comboIndex
  3. crud 操作栏里面添加了个按钮,close: true 设置是让动作完成后关闭弹窗。
  4. 按钮里面添加了 onEvent 配置,click 时做 setValue 动作,并设置参数 index 为 ‘${comboIndex}’ 值为 ${&}。其中 ${&} 是特殊语法,用来取整个上下数据。

schema: scope="body" { "type": "form", "mode": "horizontal", "api": "/api/mock2/form/saveForm", "body": [ { "type": "combo", "name": "combo", "id": "thecombo", "multiple": true, "value": [ { "engine": "" } ], "items": [ { "name": "engine", "type": "input-text" }, { "label": "Copy", "type": "button", "actionType": "dialog", "size": "md", "dialog": { "title": "历史记录", "actions": [], "data": { "comboIndex": "${index}" }, "body": [ { "type": "crud", "api": "/api/mock2/sample", "columns": [ { "label": "Engine", "name": "engine" }, { "type": "operation", "label": "操作", "buttons": [ { "label": "复制", "type": "button", "close": true, "onEvent": { "click": { "actions": [ { "componentId": "thecombo", "actionType": "setValue", "args": { "index": "${comboIndex}", "value": "${&}" } } ] } } } ] } ] } ] } } ] } ] }