# JEditableTable 帮助文档 [TOC] ## 参数配置 | 参数 | 类型 | 必填 | 说明 | |--------------|---------|------|---------------------------------------------------------------------------------| | columns | array | ✔️ | 表格列的配置描述,具体项见下表 | | dataSource | array | ✔️ | 表格数据 | | loading | boolean | | 是否正在加载,加载中不会显示任何行,默认false | | actionButton | boolean | | 是否显示操作按钮,包括"新增(编码为:add)"、"删除(编码为:batch_delete)",默认false ;如需配置按钮权限“authPre”,则此属性必须为true | | rowNumber | boolean | | 是否显示行号,默认false | | rowSelection | boolean | | 是否可选择行,默认false | | dragSort | boolean | | 是否可拖动排序,默认false,详见[拖拽排序](#拖拽排序)章节 | | dragSortKey | string | | 拖动排序存储的Key,无需定义在columns内也能在getValues()时获取到值,默认orderNum | | maxHeight | number | | 表格内容区域最大高度(px),默认400 | | disabledRows | object | | 设定禁用的行,被禁用的行无法被选择和编辑,配置方法可以查看示例 | | disabled | boolean | | 是否禁用所有行,默认false | | alwaysEdit | boolean | | 是否一直显示编辑框,如果为false则只有点击的时候才出现输入框 | | authPre| string | | 配置按钮权限所需前缀,如前缀为“myAuth”;菜单管理中为菜单添加按钮权限如“myAuth:add”;角色管理中授权即可 | ### columns 参数详解 | 参数 | 类型 | 必填 | 说明 | |---------------|---------|------|--------------------------------------------------------------------------------------------------------------------------------------------------------| | title | string | ✔️ | 表格列头显示的问题 | | key | string | ✔️ | 列数据在数据项中对应的 key,必须是唯一的 | | type | string | ✔️ | 表单的类型,可以通过`JEditableTableUtil.FormTypes`赋值 | | width | string | | 列的宽度,可以是百分比,也可以是`px`或其他单位,建议设置为百分比,且每一列的宽度加起来不应超过100%,否则可能会不能达到预期的效果。留空会自动计算百分比 | | placeholder | string | | 表单预期值的提示信息,可以使用`${...}`变量替换文本(详见`${...} 变量使用方式`) | | defaultValue | string | | 默认值,在新增一行时生效 | | validateRules | array | | 表单验证规则,配置方式见[validateRules 配置规则](#validateRules__93) | | props | object | | 设置添加给表单元素的自定义属性,例如:`props:{title: 'show title'}` | | disabled | boolean | | 是否禁用当前列,默认false | #### 当 type=inputNumber 时所需的参数 | 参数 | 类型 | 必填 | 说明 | |-------------|-------------|----------|---------| | statistics | boolean | | 是否是统计列,设置了之后会自动统计当前行的所有数据。效果: ![](https://img.kancloud.cn/f5/de/f5dec06d512c87eb151555f8db2338fe_203x279.png) | #### 当 type=checkbox 时所需的参数 | 参数 | 类型 | 必填 | 说明 | |----------------|---------|------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | defaultChecked | boolean | | 默认值是否选中 | | customValue | array | | 自定义值,checkbox需要的是boolean值,如果数据是其他值(例如`'Y' or 'N'`)时,就会导致错误,所以提供了该属性进行转换,例:`customValue: ['Y','N']`,会将`true`转换为`'Y'`,`false`转换为`'N'`,反之亦然 | #### 当 type=select 时所需的参数 | 参数 | 类型 | 必填 | 说明 | |-------------|---------|------|----------------------------------------------------| | options | array | ✔️ | 下拉选项列表,详见下表 | | allowInput | boolean | | 是否允许用户输入内容,并创建新的内容 | | allowSearch | boolean | | 是否允许用户搜索内容(仅搜索,不创建) | | dictCode | String | | 数据字典Code,若options也有值,则拼接在options后面 | - `注意事项` 1. `allowInput`和`allowSearch`不能同时使用,若同时使用,则`allowSearch`的优先级更高 2. 若`options`的某一项设置了`disabled:true`,则搜索不到该项 ##### options 所需参数 | 参数 | 类型 | 必填 | 说明 | |-----------|------------|------|----------------------------------------------------------------------| | text | string | ✔️ | 显示标题 | | value | string | ✔️ | 真实值 | | disabled | boolean | ✔️ | 是否禁用当前选项 | | ~~title~~ | ~~string~~ | | ~~显示标题(已废弃,若同时填写了 title 和 text 那么优先使用 text)~~ | #### 当 type=upload 时所需的参数 | 参数 | 类型 | 必填 | 说明 | |--------------|---------|------|--------------------------------------------------------------------------------------| | action | string | ✔️ | 上传文件路径 | | token | boolean | | 上传的时候是否传递token | | responseName | string | ✔️ | 若要从上传成功后从response中取出返回的文件名,那么这里填后台返回的包含文件名的字段名 | #### 当 type=popup 时所需的参数 | 参数 | 类型 | 必填 | 说明 | |--------------|---------|------|--------------------------------------------------------------------------------------| | popupCode | string | ✔️ | online报表编码 | | orgFields | string | ✔️ | online报表查询出来的列名,多个以逗号隔开 | | destFields | string | ✔️ | 回填到表单的列名,多个以逗号隔开。如果有多个,则顺序和orgFields一一对应,且数量必须保持一致 | | field | string | ✔️ | 从destFields中选择一个属性的值返回给当前组件 | | param | object | | 动态参数对象,在online报表参数里手动新增记录,然后就可以在自己页面里传递同名参数,作为数据查询条件,如果是字符串类型需要设置成双引号内套单引号的格式 如{name:"'admin'"} | | sorter | String | | 默认排序列,使用方法:列名=desc\|asc。例:`age=asc` `v_3.4.5`| #### 当 type=slot 时所需的参数 | 参数 | 类型 | 必填 | 说明 | |----------|--------|------|------------| | slotName | string | ✔️ | slot的名称 | ### validateRules 配置规则 `validateRules` 需要的是一个数组,数组里每项都是一个规则,规则是object类型,规则的各个参数如下 - `required` 是否必填,可选值为`true`or`false` - `unique` 唯一校验,不可重复,可选值为`true`or`false` - `pattern` 正则表达式验证,只有成功匹配该正则的值才能成功通过验证 - `handler` 自定义函数校验,使用方法请见[示例五](#示例五),注:设置了handler将不会走validateRules里handler以下的校验了,所以建议将handler放到validateRules的最下面 - `message` 当验证未通过时显示的提示文本,可以使用`${...}`变量替换文本(详见`${...} 变量使用方式`) - 配置示例请看[示例二](#示例二) ## 事件 | 事件名 | 触发时机 | 参数 | |-----------------|----------------------------------------------------|--------------------------------------------------| | added | 当添加行操作完成后触发 | | | deleted | 当删除行操作完成后触发(批量删除操作只会触发一次) | `deleteIds` 被逻辑删除的id | | selectRowChange | 当行被选中或取消选中时触发 | `selectedRowIds` 被选中行的id | | valueChange | 当数据发生改变的时候触发的事件 | `{ type, row, column, value, target }` Event对象 | ## 方法 关于方法的如何调用的问题,请在下边**FAQ**中查看方法如何调用 ### initialize 用于初始化表格(清空表格) - `参数:` 无 - `返回值:` 无 ### resetScrollTop 重置滚动条Top位置 - `参数:` | 参数名 | 类型 | 必填 | 说明 | |--------|--------|------|--------------------------------------------------------------------------------------------------------| | top | number | | 新top位置,留空则滚动到上次记录的位置,用于解决切换tab选项卡时导致白屏以及自动将滚动条滚动到顶部的问题 | - `返回值:` 无 ### add 主动添加行,默认情况下,当用户的滚动条已经在底部的时候,会将滚动条固定在底部,即添加后无需用户手动滚动,而会自动滚动到底部 - `参数:` | 参数名 | 类型 | 必填 | 说明 | |---------------------|---------|------|---------------------------------------------------------------------| | num | number | | 添加几行,默认为1 | | forceScrollToBottom | boolean | | 是否在添加后无论用户的滚动条在什么位置都强制滚动到底部,默认为false | - `返回值:` 无 ### removeRows 主动删除一行或多行 - `参数:` | 参数名 | 类型 | 必填 | 说明 | |--------|-----------------|------|--------------------------------------------------------------------------------------------| | id | string 或 array | ✔️ | 被删除行的id。如果要删除一个,可以直接传id,如果要删除多个,需要将多个id封装成一个数组传入 | - `返回值:` 无 ### removeSelectedRows 主动删除被选中的行 - `参数:` 无 - `返回值:` 无 ### getValues 用于获取表格里所有表单的值,可进行表单验证 - `参数:` | 参数名 | 类型 | 必填 | 说明 | |----------|----------|------|-----------------------------------------------------------------------------------------------------------------------------------------------------------| | callback | function | ✔️ | 获取值的回调方法,会传入`error`和`values`两个参数。`error`:未通过验证的数量,当等于`0`时代表验证通过;`values`:获取的值(即使未通过验证该字段也有数据) | | validate | boolean | | 是否进行表单验证,默认为`true`,设为`false`则代表忽略表单验证 | | rowIds | array | | 默认返回所有行的数据,如果传入了`rowIds`,那么就会只返回与该`rowIds`相匹配的数据,如果没有匹配的数据,就会返回空数组 | - `返回值:` 无 ### getValuesSync `getValues`的同步版,会直接将获取到的数据返回 - `参数:` | 参数名 | 类型 | 必填 | 说明 | |---------|--------|------|------------------------| | options | object | | 选项,详见下方所需参数 | - - `options` 所需参数 | 参数名 | 类型 | 必填 | 说明 | |----------|---------|------|----------------------------------------------------------------------------------------------------------------------| | validate | boolean | | 是否进行表单验证,默认为`true`,设为`false`则代表忽略表单验证 | | rowIds | array | | 默认返回所有行的数据,如果传入了`rowIds`,那么就会只返回与该`rowIds`相匹配的数据,如果没有匹配的数据,就会返回空数组 | - `返回值:` object - `error` 未通过验证的数量,当等于`0`时代表验证通过 - `values` 获取的值(即使未通过验证该字段也有数据) - `使用示例` ```js let { error, values } = this.$refs.editableTable.getValuesSync({ validate: true, rowIds: ['rowId1', 'rowId2'] }) if (error === 0) { console.log('表单验证通过,数据:', values); } else { console.log('未通过表单验证,数据:', values); } ``` ### getValuesPromise `getValues`的promise版,会在`resolve`中传入获取到的值,会在`reject`中传入失败原因,例如`VALIDATE_NO_PASSED` - `参数:` | 参数名 | 类型 | 必填 | 说明 | |----------|---------|------|----------------------------------------------------------------------------------------------------------------------| | validate | boolean | | 同`getValues`的`validate`参数 | | rowIds | array | | 默认返回所有行的数据,如果传入了`rowIds`,那么就会只返回与该`rowIds`相匹配的数据,如果没有匹配的数据,就会返回空数组 | - `返回值:` Promise ### getDeleteIds 用于获取被逻辑删除的行的id,返回一个数组,用户可将该数组传入后台,并进行批量删除 - `参数:` 无 - `返回值:` array ### getAll 获取所有的数据,包括values、deleteIds 会在`resolve`中传入获取到的值:`{values, deleteIds}` 会在`reject`中传入失败原因,例如`VALIDATE_NO_PASSED` - `参数:` | 参数名 | 类型 | 必填 | 说明 | |----------|---------|------|-------------------------------| | validate | boolean | | 同`getValues`的`validate`参数 | - `返回值:` Promise ### setValues 主动设置表格中某行某列的值 - `参数:` | 参数名 | 类型 | 必填 | 说明 | |--------|-------|------|------------------------------------------------------------| | values | array | | 传入一个数组,数组中的每项都是一行的新值,具体见下面的示例 | - `返回值:` 无 - `示例:` ```js setValues([ { rowKey: id1, // 行的id values: { // 在这里 values 中的 name 是你 columns 中配置的 key 'name': 'zhangsan', 'age': '20' } }, { rowKey: id2, values: { 'name': 'lisi', 'age': '23' } } ]) ``` ### clearSelection 主动清空选择的行 - `参数:` 无 - `返回值:` 无 ### getSelection `2.4.7+` 获取当前选中的行 - `参数:` 无 - `返回值:` 数组 ### setSelection `2.4.7+` 设置当前选中的行 > 如果要和设置`dataSource`同时使用,那么需要等数据处理完毕后才能调用该方法,例如下图: ![](https://img.kancloud.cn/93/b3/93b39a50ce5cc5a23577ac0d0bd997b1_462x127.png) - `参数:` * `selectedRowIds` 数组,选中行的ID - `返回值:` Promise - `示例:` ```js setSelection(['1', '2', '3']) ``` ### toggleSelectionAll `2.4.7+` 切换全选状态 - `参数:` 无 - `返回值:` 无 ## 内置插槽 | 插槽名 | 说明 | |--------------|------------------------------------------------------------| | buttonBefore | 在操作按钮的**前面**插入插槽,不受`actionButton`属性的影响 | | buttonAfter | 在操作按钮的**后面**插入插槽,不受`actionButton`属性的影响 | ## ${...} 变量使用方式 在`placeholder`和`message`这两个属性中可以使用`${...}`变量来替换文本 在[示例二](#示例二)中,配置了`title`为`名称`的一列,而`placeholder`配置成了`请输入${title}`,那么最终显示效果为`请输入名称` 这就是`${...}`变量的使用方式,在`${}`中可以使用的变量有`title`、`key`、`defaultValue`这三个属性的值 ## JEditableTableUtil 使用说明 在之前配置`columns`时提到过`JEditableTableUtil`这个工具类,那么如果想要知道详细的使用说明就请看这里 ### export 的常量 #### FormTypes 这是配置`columns.type`时用到的常量值,其中包括 - `normal` 默认,直接显示值,不渲染表单 - `input` 显示输入框 - `inputNumber` 显示数字输入框 - `checkbox` 显示多选框 - `select` 显示选择器(下拉框) - `date` 日期选择器 - `datetime` 日期时间选择器 - `upload` 上传组件(文件域) - `slot` 自定义插槽 - `hidden` 隐藏列,被隐藏的列可以正常获取赋予的原始值 ### VALIDATE_NO_PASSED 在判断表单验证是否通过时使用,如果 reject 的值 === VALIDATE_NO_PASSED 则代表表单验证未通过,你可以做相应的其他处理,反之则可能是发生了报错,可以使用 `console.error` 输出 ### 封装的方法 #### validateTables 当你的页面中存在多个JEditableTable实例的时候,如果要获取每个实例的值、判断表单验证是否通过,就会让代码变得极其冗余、繁琐,于是我们就将该操作封装成了一个函数供你调用,它可以同时获取并验证多个JEditableTable实例的值,只有当所有实例的表单验证都通过后才会返回值,否则将会告诉你具体哪个实例没有通过验证。具体使用方法请看下面的示例 - `参数:` | 参数名 | 类型 | 必填 | 说明 | |--------|-------|------|--------------------------------------------------------| | cases | array | | 传入一个数组,数组中的每项都是一个JEditableTable的实例 | - `返回值:` Promise - `示例:` ```js import { validateTables, VALIDATE_NO_PASSED } from '@/utils/JEditableTableUtil' // 封装cases let cases = [] cases.push(this.$refs.editableTable1) cases.push(this.$refs.editableTable2) cases.push(this.$refs.editableTable3) cases.push(this.$refs.editableTable4) cases.push(this.$refs.editableTable5) // 同时验证并获取多个实例的值 validateTables(cases).then((all) => { // all 是一个数组,每项都对应传入cases的下标,包含values和deleteIds console.log('所有实例的值:', all) }).catch((e = {}) => { // 判断表单验证是否未通过 if (e.error === VALIDATE_NO_PASSED) { console.log('未通过验证的实例下标:', e.index) } else { console.error('发生异常:', e) } }) ``` ## 拖拽排序 若要启用拖拽排序,只需将`dragSort`参数置为`true`即可。 开启后,在列表的最左侧会出现一个方块,如果用鼠标左键按住不动拖动的话,就可以移动整行,如果单击一下小方块的话,就会出现一个菜单,如下图所示。 ![](https://img.kancloud.cn/b8/a3/b8a315c93ae877df93c15baa38784592_244x117.png) ![](https://img.kancloud.cn/c3/5c/c35c292627bc8f73ba4617a57f5d90b5_214x183.png) 若要持久化排序顺序的话,需要传递`dragSortKey`参数,即你数据库中记录排序顺序的字段。该参数也可不传,不传默认为`orderNum` 即使你`columns`里没有定义这个字段,也可以正常获取到值,并存到数据库里。 但当给`dataSouce`赋值的时候,并不会自动处理顺序,因为这样系统性能开销太大了,所以建议查询的时候用SQL语句排好序再返回给组件使用。 ## FAQ ### 方法如何调用? 在[示例一](#示例一)中,设定了一个 `ref="editableTable"` 的属性,那么在vue中就可以使用`this.$refs.editableTable`获取到该表格的实例,并调取其中的方法。 假如我要调取`initialize`方法,就可以这么写:`this.$refs.editableTable.initialize()` ### 如何获取表单的值? 使用`getValue`方法进行获取,详见[示例三](#示例三) ### 如何进行表单验证? 在获取值的时候默认会进行表单验证操作,用户在输入的时候也会对正在输入的表单进行验证,只要配置好规则就可以了 ### 如何添加或删除一行? 该功能已封装到组件中,你只需要将 `actionButton` 设置为 `true` 即可,当然你也可以在代码中主动调用新增方法或修改,具体见上方的方法介绍。 ### 为什么使用了ATab组件后,切换选项卡会导致白屏或滚动条位置会归零? 在ATab组件中确实会导致滚动条位置归零,且不会触发`onscroll`方法,所以无法动态加载行,导致白屏的问题出现。 解决方法是在ATab组件的`onChange`事件触发时执行实例提供的`resetScrollTop()`方法即可,但是需要注意的是:代码主动改变ATab的`activeKey`不会触发`onChange`事件,还需要你手动调用下。 - `示例` ```html <template> <a-tabs @change="handleChangeTab"> <a-tab-pane tab="表格1" :forceRender="true" key="1"> <j-editable-table ref="editableTable1" :loading="tab1.loading" :columns="tab1.columns" :dataSource="tab1.dataSource"/> </a-tab-pane> <a-tab-pane tab="表格2" :forceRender="true" key="2"> <j-editable-table ref="editableTable2" :loading="tab2.loading" :columns="tab2.columns" :dataSource="tab2.dataSource"/> </a-tab-pane> </a-tabs> </template> ``` ```js /*--- 忽略部分代码片段 ---*/ methods: { /** 切换tab选项卡的时候重置editableTable的滚动条状态 */ handleChangeTab(key) { this.$refs[`editableTable${key}`].resetScrollTop() } } /*--- 忽略部分代码片段 ---*/ ``` ### slot(自定义插槽)如何使用? 代码示例请看:[示例四(slot)](#示例四(slot)) ---------------------------------------------------------------------------------------- ## 示例一 ```html <j-editable-table ref="editableTable" :loading="loading" :columns="columns" :dataSource="dataSource" :rowNumber="true" :rowSelection="true" :actionButton="true" style="margin-top: 8px;" @selectRowChange="handleSelectRowChange"/> ``` ## 示例二 ```js import { FormTypes } from '@/utils/JEditableTableUtil' /*--- 忽略部分代码片断 ---*/ columns: [ { title: '名称', key: 'name', type: FormTypes.input, placeholder: '请输入${title}', defaultValue: '称名', // 表单验证规则 validateRules: [ { required: true, // 必填 message: '${title}不能为空' // 提示的文本 }, { pattern: /^[a-z|A-Z][a-z|A-Z\d_-]{0,}$/, // 正则 message: '${title}必须以字母开头,可包含数字、下划线、横杠' } ] }, { title: '年龄', key: 'age', type: FormTypes.inputNumber, placeholder: '请输入${title}', defaultValue: 18, validateRules: [{required: true, message: '${title}不能为空'}] } ] /*--- 忽略部分代码片断 ---*/ ``` ## 示例三 ```js // 获取被逻辑删除的字段id let deleteIds = this.$refs.editableTable.getDeleteIds(); // 获取所有表单的值,并进行验证 this.$refs.editableTable.getValues((error, values) => { // 错误数 = 0 则代表验证通过 if (error === 0) { this.$message.success('验证通过') // 将通过后的数组提交到后台或自行进行其他处理 console.log(deleteIds, values) } else { this.$message.error('验证未通过') } }) ``` ## 示例四(slot) ```html <template> <j-editable-table :columns="columns" :dataSource="dataSource"> <!-- 定义插槽 --> <!-- 这种定义插槽的写法是vue推荐的新版写法(https://cn.vuejs.org/v2/guide/components-slots.html#具名插槽),旧版已被废弃的写法不再支持 --> <!-- 若webstorm这样写报错,请看这篇文章:https://blog.csdn.net/lxq_9532/article/details/81870651 --> <template v-slot:action="props"> <a @click="handleDelete(props)">删除</a> </template> </j-editable-table> </template> <script> import { FormTypes } from '@/utils/JEditableTableUtil' import JEditableTable from '@/components/jeecg/JEditableTable' export default { components: { JEditableTable }, data() { return { columns: [ // ... { title: '操作', key: 'action', width: '8%', type: FormTypes.slot, // 定义该列为 自定义插值列 slotName: 'action' // slot 的名称,对应 v-slot 冒号后面和等号前面的内容 } ] } }, methods: { /* a 标签的点击事件,删除当前选中的行 */ handleDelete(props) { // 参数解释 // props.index :当前行的下标 // props.text :当前值,可能是defaultValue定义的值,也可能是从dataSource中取出的值 // props.rowId :当前选中行的id,如果是新增行则是临时id // props.column :当前操作的列 // props.getValue :这是一个function,执行后可以获取当前行的所有值(禁止在template中使用) // 例:const value = props.getValue() // props.target :触发当前事件的实例,可直接调用该实例内的方法(禁止在template中使用) // 例:target.add() // 使用实例:删除当前操作的行 let { rowId, target } = props target.removeRows(rowId) } } } </script> ``` ## 示例五 ```js // 该示例是自定义函数校验 columns: [ { title: '字段名称', key: 'dbFieldName', type: FormTypes.input, defaultValue: '', validateRules: [ { // 自定义函数校验 handler handler(type, value, row, column, callback, target) { // type 触发校验的类型(input、change、blur、getValues) // value 当前校验的值 // callback(flag, message) 方法必须执行且只能执行一次 // flag = 是否通过了校验,不填写或者填写 null 代表不进行任何操作 // message = 提示的消息,默认使用配置的 message // target 行编辑的实例对象 if (type === 'blur' || type === 'getValues') { if (value === 'abc') { callback(false, '${title}不能是abc') // false = 未通过,可以跟自定义提示 return } let { values } = target.getValuesSync({ validate: false }) let count = 0 for (let val of values) { if (val['dbFieldName'] === value) { if (++count >= 2) { callback(false, '${title}不能重复') return } } } callback(true) // true = 通过验证 } else { callback() // 不填写或者填写 null 代表不进行任何操作 } }, message: '${title}默认提示' } ] }, ] ```