ant design vue嵌套表格及表格内部编辑的用法说明

实现效果:

因为pro手脚架中封装的s-table不支持expand和expandedRowsChange事件,无法实现根据展开节点获取其内部数据的需求,因此直接使用a-table组件

表格外层可以翻页,查询携带页码参数

<a-table
size="default"
rowKey="dict_id" //根据自己数据内部关键针设定
ref="table"
@expandedRowsChange="expandedRowsChange"
@expand="expand" // 展开表格节点操作
@change="change" // 外层表格中排序,翻页,修改页面数量等操作
:expandedRowKeys="expandedRowKeys" // 操作展开的节点
:pagination="pagination" // 页码参数
:columns="columns" // 表头
:dataSource="loadData" // 数据
>
<a-table
size="default"
style="margin-bottom:0;"
rowKey="key"
slot="expandedRowRender" // 以内层方式展现
:columns="innerColumns"
:dataSource="data"
:pagination="false"
:loading="innerloading"
@change="innerhandleChange"
>
<template v-for="(col, i) in ['item_text', 'item_value', 'item_checked', 'item_remark', 'item_sort', 'item_status']" :slot="col" slot-scope="text, record">
<a-input
:key="col"
v-if="record.editable"
style="margin: -5px 0"
:value="text"
:placeholder="innerColumns[i].title"
@change="e => handleChange(e.target.value, record.key, col)"
/>
<template v-else>{{ text }}</template>
</template> // 内部表格可编辑模板
<template slot="operation" slot-scope="text, record">
<template v-if="record.editable">
<span v-if="record.isNew">
<a @click="saveRow(record)">添加</a>
<a-divider type="vertical" />
<a-popconfirm title="是否要删除此行?" @confirm="remove(record.key)">
<a>删除</a>
</a-popconfirm>
</span>
<span v-else>
<a @click="saveRow(record)">保存</a>
<!-- <a-divider type="vertical" />
<a @click="cancel(record.key)">取消</a> -->
</span>
</template> // 内部表格新增模板
<span v-else>
<a @click="toggle(record)">编辑</a>
</span>
</template>
</a-table>
<div
slot="expandedRowRender"
style="margin: 0">
<a-button style="width: 100%; margin-top: 16px; margin-bottom: 8px" type="dashed" icon="plus" @click="newMember">新增属性</a-button>
</div>
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)">编辑</a>
</span>
</a-table>

主要数据:

  expandedRowKeys: [],
  // 表头
  columns: [
  {
   title: '字典编码',
   dataIndex: 'dict_code'
  },
  {
   title: '字典名称',
   dataIndex: 'dict_name'
  },
  {
   title: '状态',
   dataIndex: 'dict_status'
  },
  {
   title: '字典描述',
   dataIndex: 'dict_remark'
  }, {
   title: '操作',
   width: '150px',
   dataIndex: 'action',
   scopedSlots: { customRender: 'action' }
  }
  ],
  loadData: [],
  innerColumns: [
  {
   title: '字段名',
   dataIndex: 'item_text',
   key: 'item_text',
   width: '15%',
   scopedSlots: { customRender: 'item_text' }
  },
  {
   title: '字段值',
   dataIndex: 'item_value',
   key: 'item_value',
   width: '15%',
   scopedSlots: { customRender: 'item_value' }
  },
  {
   title: '默认选中(0:否,1:是)',
   dataIndex: 'item_checked',
   key: 'item_checked',
   width: '10%',
   scopedSlots: { customRender: 'item_checked' }
  },
  {
   title: '备注',
   dataIndex: 'item_remark',
   key: 'item_remark',
   width: '20%',
   scopedSlots: { customRender: 'item_remark' }
  },
  {
   title: '排序号',
   dataIndex: 'item_sort',
   key: 'item_sort',
   width: '10%',
   sorter: true,
   scopedSlots: { customRender: 'item_sort' }
  },
  {
   title: '状态(1:正常,2:异常)',
   dataIndex: 'item_status',
   key: 'item_status',
   width: '10%',
   scopedSlots: { customRender: 'item_status' }
  },
  {
   title: '操作',
   key: 'action',
   scopedSlots: { customRender: 'operation' }
  }
  ],
  data: [],
  innerloading: false,
  parameter: {
  pageNo: 1,
  pageSize: 10
  },
  // 排序参数
  sortedInfo: null,
  pagination: {
  total: 1,
  current: 1,
  showTotal: total => `共 ${total} 条记录 第 ${this.pagination.current} / ${Math.ceil(total / this.pagination.pageSize)} 页`,
  showQuickJumper: true,
  showSizeChanger: true,
  pageSize: 10
  }

初始进入页面时,需要获取外层表格

使用初始参数parameter请求第一页数据,从返回数据中对pagination重置翻页组件内部参数,主要有当前页,页码总量,页码大小

getDictList(this.parameter)
  .then(res => {
   if (res.code === '200') {
   console.log(res)
   this.loadData = res.data
   this.pagination.total = res.totalCount
   this.pagination.current = res.pageNo
   this.pagination.pageSize = res.pageSize
   } else {
   this.$message.error(res.message)
   }
  })

展开外层数据节点获取内部数据:

expand (expanded, record) {
  this.expandedRowKeys = [] // 重置展开节点,只展开当前点击的节点(内部数据调用模板,无法做到同时几个内层表格数据直接缓存在页面)
  if (expanded) {
  this.expandedRowKeys = [record.dict_id]
  this.getDictItem() // 获取表格内部数据
  }
  console.log(expanded, record)
 },
// 展开节点后获取内部表格数据
getDictItem (obj) {
  let searchparam = { dict_id: this.expandedRowKeys[0] }
  if (obj) { // 内部表格除了根据其父节点id查找的条件外,还支持排序,因此需要整合排序参数
  searchparam = Object.assign(searchparam, obj)
  }
  this.innerloading = true
  getDictItemList(searchparam).then(res => {
  if (res.code === '200') {
   this.data = res.data
   this.innerloading = false
  } else {
   this.$message.error(res.message)
  }
  })
 },
// 外层表格操作
 change (pagination, filters, sorter) { // 对页面大小,筛选,排序等条件修改后重新查询数据
  this.pagination = pagination
  this.parameter.pageNo = pagination.current
  this.parameter.pageSize = pagination.pageSize
  this.getDict()
  console.log('pagination', pagination)
  console.log('filters', filters)
  console.log('sorter', sorter)
 },
 /* 内层表格操作 */
 innerhandleChange (pagination, filters, sorter) {
  console.log('Various parameters', pagination, filters, sorter)
  this.sortedInfo = {
  sortField: sorter.field,
  sortOrder: sorter.order
  }
  this.getDictItem(this.sortedInfo)
 },

至此,展示功能已经几乎做完啦,现在是内部表格的编辑与新增功能

handleChange (value, key, column) { // 实时更新表格中各个输入框的状态
  const newData = [...this.data]
  const target = newData.filter(item => key === item.key)[0]
  if (target) {
  target[column] = value
  this.data = newData
  }
 },
 toggle (data) { // 切换输入框与文本状态,实现展示与编辑功能
  const target = this.data.filter(item => item.key === data.key)[0]
  target.editable = !target.editable
  console.log(this.data)
 },
 newMember () { // 新增内容后的数据字段
  this.data.push({
  'item_text': '',
  'item_value': '',
  'item_checked': '',
  'item_remark': '',
  'item_sort': '',
  'item_status': '',
  key: this.data.length,
  editable: true,
  isNew: true
  })
 },
 saveRow (record) {
  this.innerloading = true
  if (!record.item_text || !record.item_value) { // 对必填项进行管控
  this.innerloading = false
  this.$message.error('请至少填写填写字段名和字段值。')
  return
  }
  record.item_checked = record.item_checked || 0 // 设置默认值
  record.item_sort = record.item_sort || 1
  record.item_status = record.item_status || 1
  record.dict_id = this.expandedRowKeys[0]
  if (record.item_id) { // 修改
  updateItem(record).then(res => {
   if (res.code === '200') {
   this.$message.success(res.message)
   this.getDictItem() // 修改成功后重新获取当前内部表格数据
   } else {
   this.$message.error(res.message)
   }
  })
  } else {
  addItem(record).then(res => {
   if (res.code === '200') {
   this.$message.success(res.message)
   this.getDictItem()
   } else {
   this.$message.error(res.message)
   }
  })
  }
 },
 cancel (key) {
  const target = this.data.filter(item => item.key === key)[0]
  target.editable = false
 },
 remove (key) {
  const newData = this.data.filter(item => item.key !== key)
  this.data = newData
 },
 /* 内层表格操作结束 */

外层表格与内存表格数据示例:

{
 "success": true,
 "code": "200",
 "message": "分页查询成功",
 "data": [{
 "dict_id": 1,
 "dict_code": "common_org_type",
 "dict_name": "机构类别",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": "机构类别"
 }, {
 "dict_id": 2,
 "dict_code": "common_user_type",
 "dict_name": "人员类别",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": "人员类别"
 }, {
 "dict_id": 48,
 "dict_code": "cdsfcsdcf",
 "dict_name": "修改属性1",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": ""
 }, {
 "dict_id": 49,
 "dict_code": "bugbugbug",
 "dict_name": "有字典id",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": ""
 }, {
 "dict_id": 50,
 "dict_code": "1",
 "dict_name": "名称",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": "1"
 }, {
 "dict_id": 51,
 "dict_code": "1",
 "dict_name": "1",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": null
 }, {
 "dict_id": 52,
 "dict_code": "1",
 "dict_name": "1",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": null
 }, {
 "dict_id": 53,
 "dict_code": "1",
 "dict_name": "1",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": null
 }, {
 "dict_id": 54,
 "dict_code": "1",
 "dict_name": "1",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": ""
 }, {
 "dict_id": 55,
 "dict_code": "dbhasuiuh",
 "dict_name": "测试字典1",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": "备注"
 }],
 "totalCount": 11,
 "pageNo": 1,
 "pageSize": 10,
 "totalTag": 1
}
{
 "success": true,
 "code": "200",
 "message": "查询成功",
 "data": [{
 "item_id": 2,
 "dict_id": 1,
 "item_text": "外部",
 "item_value": "2",
 "item_status": 1,
 "item_sort": 2,
 "item_remark": null,
 "item_checked": 1,
 "editable": 0 // 写死就行了 一定要有 用于内部表格编辑功能
 }, {
 "item_id": 1,
 "dict_id": 1,
 "item_text": "内部",
 "item_value": "1",
 "item_status": 1,
 "item_sort": 1,
 "item_remark": "1",
 "item_checked": 1,
 "editable": 0
 }]
}

补充知识:ant design Table可编辑的单元格改进版

antd官方也有给文档,但是超级麻烦,代码量还超级多,改编了一下

如图:

这里table的columns的写法,如下:

const columns2 = [
{
title: '尺寸名称',
dataIndex: 'name',
filterDropdown: true,
filterIcon: <Icon type="edit"/>,
render: () => <Input />,
},
{
title: '标准尺寸',
dataIndex: 'standard',
filterDropdown: true,
filterIcon: <Icon type="edit"/>,
render:() => <Input />,
},
{
title: '上偏差',
dataIndex: 'upper_deviation',
filterDropdown: true,
filterIcon: <Icon type="edit"/>,
render:() => <Input />,
},
{
title: '下偏差',
dataIndex: 'lower_deviation',
filterDropdown: true,
filterIcon: <Icon type="edit"/>,
render: () => <Input />,
},
{
title: '工序',
dataIndex: 'procedure',
filterDropdown: true,
filterIcon: <Icon type="edit"/>,
render: () =>
<Select>
  <Option value='1'>1</Option>
  <Option value='2'>2</Option>
</Select>
},
{
title: '操作',
dataIndex: 'operation',
render: (text, record) => (
this.state.size.length >= 1
? (
<Popconfirm title="确定删除该信息?" onConfirm={() => this.handleDelete(record.key)}>
<a href="javascript:;">删除</a>
</Popconfirm>
) : null
),
}
];

其中

filterDropdown: true,

filterIcon: <Icon type="edit"/>,

这两个是用于给表头添加图标,不需要可以不写

实现可编辑表格最重要的是吧这个表格所有字段都变成可控字段,这样就可以实现对表格数据的提交的基本操作

就拿我这里面的尺寸名称来说,这个字段叫name ,这里的render就要修改成render: (text, record) => <Input value={text} onChange={(e) => this.handleChange({name: e.target.value}, record)}/>,

这里参数text可以理解为 input的初始值,onChange事件是吧这个input变成可控的组件,handleChange这里有两个参数,这里“”name: e.target.value“”必须要这么传,目的是把改组件的值跟name进行绑定。

handleChange 方法

handleChange = (value, record) => {
for (var i in value) {
record[i] = value[i];//这一句是必须的,不然状态无法更改
this.setState({
size: this.state.size.map((item, key) => item.key == record.key ? {...item, [i]: value[i]} : item)
})
}
}

这里我把这个可编辑表格的值存在state中的size中,通过key进行匹配(这里key代表我这个表格的rowkey,也就是用来区分行数据的一个标识),然后修改指定行的指定数据,通过改变state中的size更新视图,同时吧更改的数据替换掉原来的 这就实现了对表格数据的实时监听,同时表格的所有数据存在了state中的size中,想要获取表格数据直接用this.state.size即可。

(这里需要注意的时,如果把表格中的某个字段,比如说name设置成表格的rowkey,就会发生name字段只能输入单个字符就会失去焦点的情况)

以上这篇ant design vue嵌套表格及表格内部编辑的用法说明就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 解决ant design vue 表格a-table二次封装,slots渲染的问题

    目的就是对a-table进行二次封装,但是在如何显示a-table的slot时遇到了问题,原本想法是在a-table内把$slots都渲染,期望在使用该组件时能正确渲染,然而...并不会正确渲染 <template> <a-table bordered :scroll="{ x: scrollX, y: 600 }" v-bind="{...$attrs, ...$props, ...{dataSource: body, columns: header}}&

  • Ant design vue table 单击行选中 勾选checkbox教程

    最近了解Ant design 设计table 单击行选中checkedbox功能,相比于element的 @row-click 再触发toggleRowSelection,ant design的api就没那么清晰了,言归正传 期望:Ant design table 单击行选中 勾选checkedbox 实现: 单选: onClickRow(record) { return { on: { click: () => { let keys = []; keys.push(record.id); th

  • Antd的Table组件嵌套Table以及选择框联动操作

    一.需求 在使用Table组件嵌套Table时,父子Table的选择框需要联动,即父Table选中,该行下的子Table需要全选中,某一个子Table全部选中,则该子Table所在的父Table那一行也需要选中. 二.Table的rowSelection配置 父子Table联动,就不能使用OnChange,需要使用OnSelect以及OnSelectAll手动配置. selectedRowKeys:指定选中项的key数组 OnSelect:手动选择/取消选择某行的回调 OnSelect(reco

  • ant design vue嵌套表格及表格内部编辑的用法说明

    实现效果: 因为pro手脚架中封装的s-table不支持expand和expandedRowsChange事件,无法实现根据展开节点获取其内部数据的需求,因此直接使用a-table组件 表格外层可以翻页,查询携带页码参数 <a-table size="default" rowKey="dict_id" //根据自己数据内部关键针设定 ref="table" @expandedRowsChange="expandedRowsChan

  • ant design vue中日期选择框混合时间选择器的用法说明

    首先时间格式化用到moment方法,需要在页面中引入moment组件 import moment from 'moment' 结构代码: <a-date-picker style="width:100%" :getCalendarContainer="(triggerNode) => triggerNode.parentNode" format="YYYY-MM-DD HH:mm:ss" v-decorator="[ 'pu

  • ant design vue中表格指定格式渲染方式

    注意点:定义的columns一定要写在data中,否则在加载过程中由于渲染顺序会导致其中的渲染函数无法识别 渲染方法1: 指定渲染函数: const columns = [ { title: '排名', dataIndex: 'key', customRender: renderContent // 渲染函数的规则 }, { title: '搜索关键词', dataIndex: 'keyword', customRender: (text, row, index) => { if (index

  • ant design vue 表格table 默认勾选几项的操作

    为什么我同样的功能要用react .vue 都写一遍 ? 啊我真是不是闲的蛋疼啊(- o -)~zZ 在 ant design vue 中,表格的第一列是联动的选择框 截一张官方文档图,图示最后一排就是禁用状态 点击 checkbox 会触发onChange , 从而得到selectedRowKeys,selectedRowKeys就是选中的 key 数组. onChange: (selectedRowKeys, selectedRows) => { console.log(`selectedR

  • Ant Design Vue 修改表格头部样式的详细代码

    在网上搜了好多修改表格头部样式的,最后自己摸索出来,分享给大家,最后附上完整代码.首先用到的是customHeaderRow这个API,类型是一个函数 1.HTML部分 <a-table size='small' // 样式大小 :columns="columns" :data-source="data" bordered :pagination="false" // 不显示页数 :customHeaderRow="customR

  • ant design中实现table的表格行的拖拽

    前言: 首先刚开始知道要书写一个这样的功能我的内心是比较崩溃的 完全没有思路,   然后就打开官网的文档进行观看.一开始准备写 打开官网的一个文档是4.0的 看起来也是一脸的蒙蔽,接着找到3的一个文档,接下来直接说说如何让实现当前这个功能上代码 代码部分: import { Table } from 'antd'; import { DndProvider, DragSource, DropTarget } from 'react-dnd'; import { HTML5Backend } fr

  • Ant Design Vue中的table与pagination的联合使用方式

    目录 Ant Design Vue中table与pagination联合使用 ant.design.vue中table的使用说明 table的创建 table之columns table之dataSource table之loading table之scroll table之rowKey table之rowSelection table之customRow table之change Ant Design Vue中table与pagination联合使用 表格table使用链接:ant desig

  • Ant design vue中的联动选择取消操作

    项目中会遇到需求就是table表格中选中在侧边展示,侧边删除,table中选中取消的联动选中 ui框架:Ant design vue 组件:table 和 tag html中 <template v-for="tag in dataType"> <!-- key不能使用index --> <a-tag :key="tag.id" closable :afterClose="() => deleteDataType(tag

随机推荐