Table 进阶

经过前几章的学习,我们已经了解了开发复杂界面的基本知识,接下来我们逐步扩展之前的 Table,实践一下对应知识点。

需要大致实现的 Table:

sqI5kj.png

可以看到对比之前的 Table 功能点多了很多,具体需求如下:

  1. 添加字段
  2. 行内编辑
  3. 对相关字段做必要补充说明
  4. 年龄大于 18,性别必输
  5. 年龄输入范围需大于 1 小于 100
  6. 年龄可排序
  7. 姓名必输,且为主键、唯一
  8. 邮箱后缀自动填充
  9. 存在查询条,可搜索查询
  10. 添加操作按钮

同样的我们从 DataSet 结合要显示的数据入手进行扩展。

功能扩展

从界面上可得出,我们扩展新增了三个字段:年龄(age)、邮箱(email)、加入日期(startDate)。

  1. fields 数组中初步添加字段配置,完成第一点。
  1. {
  2. name: 'age',
  3. type: 'number',
  4. label: '年龄',
  5. },
  6. {
  7. name: 'email',
  8. type: 'string',
  9. label: '邮箱',
  10. },
  11. {
  12. name: 'startDate',
  13. type: 'date',
  14. label: '加入日期',
  15. }
  1. Table 支持行内编辑。编辑组件载体为 Table,我们查看 Table 组件 API,columns 对象添加 editor 属性即可实现行内编辑。
属性名描述类型
editor编辑器, 设为true时会根据 field 的 type 自动匹配编辑器。不可编辑请使用false值,而不是在控件上加 disabled。FormField | ((record, name) => FormField | boolean) | boolean
  1. [
  2. { name: 'name', editor: true },
  3. { name: 'age', editor: true },
  4. { name: 'sex', editor: true },
  5. { name: 'email', editor:true },
  6. { name: 'code', editor: true },
  7. { name: 'startDate', editor: true },
  8. { name: 'active', editor: true },
  9. ]
  1. 对相关字段做补充说明。处理对象为字段,查看 API 可得 help 属性。完善对应字段配置。
属性名描述类型
help额外信息,常用于提示string
  1. {
  2. name: 'name',
  3. type: 'string',
  4. label: '姓名',
  5. help: '主键,区分用户',
  6. },
  7. {
  8. name: 'age',
  9. type: 'number',
  10. label: '年龄',
  11. help: '用户年龄,可以排序',
  12. },
  13. {
  14. name: 'email',
  15. type: 'string',
  16. label: '邮箱',
  17. help: '用户邮箱,可以自动补全',
  18. },

实现效果:

sqoR81.png sqo2CR.png

  1. 年龄大于 18,性别字段必输。分析需求,需要动态处理性别字段配置,可使用我们上一章提到的dynamicProps。
  1. {
  2. name: 'sex',
  3. ...
  4. dynamicProps: {
  5. required: ({ record }) => record.get('age') > 18,
  6. },
  1. 年龄输入范围需大于 1 小于 100。普通组件库需要在输入时判断处理,这里我们同样可以使用字段属性配置 - min / max。可配置类型:字段名 | 数字 | 日期。
属性名描述类型
max最大值。 fieldName 指向当前记录的 fieldName 值作为最大值。number | MomentInput | fieldName
min最小值。 fieldName 指向当前记录的 fieldName 值作为最小值。number | MomentInput | fieldName

这里我们修改年龄字段:

  1. {
  2. name: 'age',
  3. type: 'number',
  4. label: '年龄',
  5. max: 100,
  6. min: 1,
  7. step: 1,
  8. help: '用户年龄,可以排序',
  9. },
  1. 年龄字段支持表格排序。这里处理对象在表格,查看文档可得 sortable 属性。
属性名描述类型默认值
sortable是否可排序(后端请求排序,前端排序请自定义 header 自行实现)booleanfalse
  1. { name: 'age', sortable: true, editor: true },
  1. 姓名必输,且为主键、唯一。查看 field props 修改姓名字段配置。
  1. {
  2. name: 'name',
  3. type: 'string',
  4. label: '姓名',
  5. unique: true, // 唯一索引或联合唯一索引组名 设置可编辑只有新增才能编辑,确保该字段或字段组唯一性
  6. help: '主键,区分用户',
  7. required: true,
  8. },
  1. 邮箱后缀自动填充。

具体表现为输入时自动补足已有的邮箱后缀,这里我们常用的组件是AutoComlpete。邮箱后缀的数据源可前端写死也可后端查询维护。

这里我们做一下实现步骤拆解:

  1. 1. 行内编辑器根据 type 默认匹配 EmailField 组件,我们需要修改为 AutoComlpete 组件
  2. 2. AutoComlpete 组件配置自动补全数据源,对应 options 属性
  3. 3. 处理 AutoComlpete 输入获焦事件,判断是否需要后缀

a. 修改 email 列 editor 属性,替换默认编辑器:

  1. {
  2. name: 'email',
  3. editor: () => {
  4. return (
  5. <AutoComplete
  6. onFocus={handleValueChange}
  7. onInput={handleValueChange}
  8. options={emailOptionDS}
  9. />
  10. );
  11. },
  12. },

b. 处理数据源 emailOptionDS(这里类似 Select 组件数据源操作,后续详解):

  1. const emailOptionDS = useMemo(() => {
  2. return new DataSet({
  3. fields: [
  4. {
  5. name: 'value',
  6. type: 'string',
  7. },
  8. {
  9. name: 'meaning',
  10. type: 'string',
  11. },
  12. ],
  13. });
  14. }, []);

c. 处理组件上的事件,为数据源 emailOptionDS 加载数据:

  1. const handleValueChange = useCallback((v) => {
  2. const { value } = v.target;
  3. const suffixList = ['@qq.com', '@163.com', '@hand-china.com'];
  4. if (value.indexOf('@') !== -1) {
  5. // 如果输入值中包含 @ 不配置数据,自定义输入
  6. emailOptionDS.loadData([]);
  7. } else {
  8. emailOptionDS.loadData(
  9. suffixList.map((suffix) => ({
  10. value: `${value}${suffix}`,
  11. meaning: `${value}${suffix}`,
  12. })),
  13. );
  14. }
  15. }, [emailOptionDS]);

处理完毕,编辑邮箱字段看看效果:

sqoWgx.png

  1. 为 Table 配置查询条,支持查询条件。这里就应用到 DataSet queryFields 结合 Table queryBar属性了,queryFields 用法同 fields:
属性名描述类型
queryFields查询字段属性数组,在内部生成 queryDataSet,优先级低于 queryDataSet 属性,详见Field Propsobject[]

我们配置三个查询条件:姓名、年龄、邮箱:

  1. queryFields: [
  2. {
  3. name: 'name',
  4. type: 'string',
  5. label: '姓名',
  6. },
  7. {
  8. name: 'age',
  9. type: 'number',
  10. label: '年龄',
  11. max: 100,
  12. step: 1,
  13. },
  14. {
  15. name: 'email',
  16. type: 'string',
  17. label: '邮箱',
  18. help: '用户邮箱,可以自动补全',
  19. }
  20. ],

这时界面对应渲染如下:

sqofv6.png

查看 Table queryBar 属性,默认类型为 normal,我们试试使用 professionalBar:

属性名描述类型默认值
queryBar查询条, 可选值为钩子或者内置类型:filterBar | professionalBar | advancedBar | normal | bar | nonestring | ({ dataSet, queryDataSet, buttons, pagination, queryFields, queryFieldsLimit }) => ReactNodenormal
  1. queryBar="professionalBar"

sqo4KK.png

可以看到对应搜索条和我们想要的一行展示数量还是不同,查找 API 可得:

属性名描述类型
queryFieldsLimit头部显示的查询字段的数量,超出限制的查询字段放入弹出窗口number
  1. queryFieldsLimit={2}

最终效果:

sqoTVe.png

可尝试修改 queryBar 为其他类型,看看不同的预置查询交互吧。如果都不符合产品需求,也支持自定义并全局配置的。

  1. 添加操作按钮。这块便于教学,配置 Table buttons 添加了以下 8 个按钮:
属性名描述类型
buttons功能按钮,内置按钮可添加afterClick钩子,用于执行除了默认行为外的动作,可选值:adddeleteremovesavequeryresetexpandAllcollapseAllexport或 数组 或 自定义按钮,数组为可选值字符串+按钮配置属性对象string | [string, object] | ReactNode | object
  1. buttons={['add', 'query', 'save', 'delete', 'reset', toDataButton, toJSONDataButton, setQueryParamButton]}
  1. 新增
  2. 查询
  3. 保存
  4. 删除
  5. 重置
  6. toDataButton - tableDS.toData()
  7. toJSONDataButton - tableDS.toJSONData()
  8. setQueryParamButton - tableDS.setQueryParameter(‘customPara’, ‘test’)

前五个为预置按钮类型,内置封装对应含义逻辑。后三个为演示自定义逻辑触发按钮:

  1. const [consoleValue, setConsoleValue] = useState('');
  2. const toDataButton = (
  3. <Button onClick={() => setConsoleValue(tableDS.toData())}>
  4. toData
  5. </Button>
  6. );
  7. const toJSONDataButton = (
  8. <Button onClick={() => setConsoleValue(tableDS.toJSONData())}>
  9. toJSONData
  10. </Button>
  11. );
  12. const setQueryParamButton = (
  13. <Button onClick={() => tableDS.setQueryParameter('customPara', 'test')}>
  14. setQueryParameter
  15. </Button>
  16. );

输出验证

这里我们将对应变化内容使用CodeArea组件做了展示。

  1. import {
  2. CodeArea
  3. } from 'choerodon-ui/pro';
  4. // 引入格式化器,注意使用模块的默认导出
  5. import JSONFormatter from 'choerodon-ui/pro/lib/code-area/formatters/JSONFormatter';
  6. //return中添加
  7. <CodeArea
  8. style={{ height: 280 }}
  9. formatter={JSONFormatter}
  10. value={JSON.stringify(consoleValue)}
  11. />

sqo5DO.png

输出展示内容:

  1. DataSet events 中 query 事件查询参数
  2. toDataButton & toJSONDataButton 调用方法
  3. 提交 transport create 类型参数

首先我们应用了 DataSet events 事件:

  1. // DS 事件回调
  2. events: {
  3. load: ({ dataSet }) => {
  4. console.log('加载完成', dataSet)
  5. },
  6. query: ({ params, data }) => setConsoleValue({params, data}),
  7. }
  • load -数据加载完后事件
  • query - 查询事件,返回值为 false 将阻止查询

更多事件 -events.

因此初始查询后,我们输出观察到分页查询参数。

点击 toDataButton 或 toJSONDataButton,查看对应输出:

sqoIbD.pngsqo7UH.png

  • toData() - 转换成普通数据,不包含删除的数据
  • toJSONData() - 转换成用于提交的 json 数据

toJSONData() 输出为 [],可得出无提交数据,这里就涉及到上一章提到的 dataToJSON 属性,修改 DataSet dataToJSON 为 “all”,点击按钮:

sqoH5d.png

验证设置查询参数:

  1. 在查询条组件内输入内容,点击查询:

sqoqPA.png

  1. 点击 setQueryParameter 按钮,点击查询:

sqoL8I.png

可见默认参数都会处理进 data 对象中。

剩下的预置按钮行为自己再操作输出查看一下吧。

演示案例只有查询接口。保存、排序等操作均仅做数据输出演示。

本章对 Table 进行了进阶实践,下一章实践一下 Pro Form 组件。