赞
踩
下面是一个可以实现编辑的表格,并且该表格嵌入在form表单内,可以对已修改的内容进行保存提交;而且实现了对表格数据进行关键字搜索和分类筛选的功能,实现了前端分页的效果。
(1)当el-table列数据过多时,我们可以通过设置 type="expand" 和 Scoped slot
可以开启展开行功能,然后在每一行设置一个可编辑按钮,对展开的数据中的某条数据进行再编辑。
(2)当你设置可编辑按钮时,还要对此行展开状态进行判断,判断该行是否为展开,若已展开,则编辑,若未展开,则展开进行编辑。
(3)当对某一行进行编辑时,如该行未确认完成编辑,则不能对其他行再进行编辑,需要对该行确认完成编辑,才可对其他行进行编辑操作。
(4)对数据进行分页展示。
(5)对数据进行关键字搜索和根据分类对每页数据进行筛选。
(6)保存和提交数据的检验。
可编辑el-table表格演示视频
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>可编辑表格</title>
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
- <script src="../vue/vue.min.js" type="text/javascript" charset="utf-8"></script>
- <script src="../elementUI/index.js" type="text/javascript" charset="utf-8"></script>
- <script src="../vue/axios.min.js" type="text/javascript" charset="utf-8"></script>
- <link rel="stylesheet" type="text/css" href="../elementUI/index.css" />
- <style type="text/css">
- .menu {
- width: 100%;
- height: 100%;
- }
-
- .container_table {
- width: 100%;
- }
-
- .el-table .cell {
- text-align: center;
- }
-
- .postForm {
- width: 340px;
- height: 40px;
- float: right;
- margin-top: -40px;
- }
-
- /* 展开的form样式 */
- .demo-table-expand label {
- width: 90px;
- color: #99a9bf;
- }
-
- .el-form--label-left .el-form-item__label {
- text-align: right;
- }
-
- .demo-table-expand .el-form-item {
- margin-right: 0;
- margin-bottom: 0;
- width: 30%;
- }
-
- .container_table .fy {
- margin-top: 20px;
- }
- </style>
- </head>
- <body>
- <div id="menu" class="menu">
- <el-container>
- <div class="container_table">
- <el-form :model="tableData" @submit.native.prevent>
- <el-table ref="refTable" height="500" :data="tableData.slice((currentPage-1)*pagesize,currentPage*pagesize)"
- style="width: 100%" @expand-change="expandChange">
- <el-table-column type="expand">
- <template slot-scope="props">
- <el-form label-position="left" inline class="demo-table-expand">
- <el-form-item label="日期">
- <span>{{ props.row.date }}</span>
- </el-form-item>
- <el-form-item label="姓名">
- <span>{{ props.row.name }}</span>
- </el-form-item>
- <el-form-item label="手机号">
- <span v-if="props.row.isSet">{{props.row.phone}}</span>
- <span v-else>
- <el-input clearable v-model="props.row.phone"></el-input>
- </span>
- </el-form-item>
- <el-form-item label="地址">
- <span v-if="props.row.isSet">{{props.row.address}}</span>
- <span v-else>
- <el-input type="textarea" clearable autosize v-model="props.row.address"></el-input>
- </span>
- </el-form-item>
- <el-form-item label="部门">
- <span>{{ props.row.tag }}</span>
- </el-form-item>
- </el-form>
- </template>
- </el-table-column>
- <el-table-column prop="date" label="日期" sortable width="120" column-key="date">
- </el-table-column>
- <el-table-column prop="name" label="姓名">
- </el-table-column>
- <el-table-column prop="phone" label="手机号">
- </el-table-column>
- <el-table-column prop="address" label="地址">
- </el-table-column>
- <el-table-column prop="tag" label="部门" width="140" :filters="sectorData" :filter-method="filterTag">
- <template slot-scope="scope">
- <el-tag size="medium" disable-transitions>{{scope.row.tag}}</el-tag>
- </template>
- </el-table-column>
- <el-table-column prop="searchInfo" width="200">
- <template slot="header" slot-scope="scope">
- <el-input clearable v-model="search" prefix-icon="el-icon-search" size="mini" placeholder="输入姓名关键字搜索" @input="searchName" />
- </template>
- <template slot-scope="scope">
- <el-button :disabled="btnDisabled" plain icon="el-icon-edit" v-if="scope.row.isSet" @click="handleEdit(scope.$index, scope.row)"
- size="mini">编辑</el-button>
- <el-button plain v-else @click="saveEdit(scope.$index, scope.row)" size="mini">确定</el-button>
-
- </template>
- </el-table-column>
- </el-table>
- </el-form>
- <el-pagination class="fy" :current-page="currentPage" :page-sizes="[5, 10, 20]" :page-size="pagesize" layout="total, sizes, prev, pager, next, jumper"
- @size-change="handleSizeChange" @current-change="handleCurrentChange" :total="tableData.length" background>
- </el-pagination>
- <div class="postForm">
- <el-button icon="el-icon-finished" type="primary" @click="postForm">提交</el-button>
- <el-button icon="el-icon-check" type="success" @click="saveForm">保存</el-button>
- <el-button icon="el-icon-back" type="info" @click="backtrack">撤回</el-button>
- </div>
- </div>
- </el-container>
- </div>
- </body>
- <script type="text/javascript">
- var vm = new Vue({
- el: '#menu',
- data() {
- return {
- /* 表格数据 */
- tableData: [],
- /* 原始表格数据 */
- oldtableData: [],
- /* 部门数据 */
- sectorData: [],
- pagesize: 5, //每页的数据条数
- currentPage: 1, //默认开始页面
- search: '', //搜索关键字
- btnDisabled: false,
- };
- },
- methods: {
- /* 部门筛选 */
- filterTag(value, row, column) {
- console.log(value);
- // console.log(row);
- return row.tag === value;
- },
- /* 分页方法 */
- handleSizeChange(val) {
- // console.log(`每页 ${val} 条`);
- this.pagesize = val;
- },
- handleCurrentChange: function(val) {
- // console.log(`当前页: ${val}`);
- this.currentPage = val;
- },
- /* 姓名关键字搜索 */
- searchName(search) {
- var newList = [];
- // console.log(search);
- if (search != '') {
- vm.oldtableData.forEach(item => {
- if (item.name.indexOf(search) != -1) {
- //空字符串包含在所有字符串中,因此控制会返回所有列表
- newList.push(item);
- }
- });
- return this.tableData = newList;
- } else {
- return this.tableData = this.oldtableData;
- }
-
- },
- /* 更改每一行的张开/关闭状态 */
- expandChange(row, expandedRows) {
- row.isExpand = !row.isExpand;
- },
- /* 开启编辑单元格 */
- handleEdit(index, row, e) {
- for (const i of this.tableData) {
- if (!i.isSet) {
- return this.$message.warning('请先保存当前编辑项');
- }
- }
- if (!row.isExpand) {
- //调用,table的方法,展开/折叠 行
- this.$refs.refTable.toggleRowExpansion(row);
- }
- row.isSet = false;
-
- },
- /* 保存单元格,进行编辑验证 */
- saveEdit(index, row, column) {
- // console.log(row);
- if ((row.address.replace(/\s+/g, '') == '' || (row.phone.replace(/\s+/g, '') == ''))) {
- row.isSet = false;
- return this.$message.error('数据不能为空');
- } else {
- row.isSet = true;
- }
- //调用,table的方法,展开/折叠 行
- this.$refs.refTable.toggleRowExpansion(row);
- },
- /* 提交表单 */
- postForm() {
- if (!this.btnDisabled) {
- return this.$message.error('请先保存');
- } else {
- this.$confirm('是否提交?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- }).then((action) => {
- this.$message({
- type: 'success',
- message: '提交成功!',
-
- });
- if (action === 'confirm') {
- //提交表单
- console.log(this.tableData);
- }
- }).catch(() => {
- this.$message({
- type: 'info',
- message: '已取消提交!'
- });
- });
- }
- },
- /* 保存表单 */
- saveForm() {
- for (var i = 0; i < this.tableData.length; i++) {
- if (!this.tableData[i].isSet) {
- this.$message.warning('请先保存当前编辑项');
- return this.btnDisabled = false;
- } else {
- this.btnDisabled = true;
- }
- }
- },
- /* 撤回保存 */
- backtrack() {
- this.btnDisabled = false;
- },
- /* 获取内容数据 */
- getTableData() {
- axios.get('../data/tableData.json', {})
- .then(function(res) {
- for (var i = 0; i < res.data[0].tableData.length; i++) {
- // 添加单元格是否可以编辑的属性值
- res.data[0].tableData[i].isSet = true;
- // 添加行是否展开的属性值
- res.data[0].tableData[i].isExpand = false;
- }
- console.log(res.data);
- // 赋值
- vm.tableData = res.data[0].tableData;
- vm.oldtableData = res.data[0].tableData;
- vm.sectorData = res.data[1].sectorData;
- }).catch(function(error) {
- console.log(error);
- });
- }
- },
- mounted() {
- // 获取内容数据
- this.getTableData();
- }
-
- });
- </script>
- </html>
- [{
- "tableData": [{
- "date": "2016-05-01",
- "name": "张晓明",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 11 弄",
- "tag": "设计三所"
-
- }, {
- "date": "2016-05-02",
- "name": "李米中",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 12 弄",
- "tag": "设计二所"
-
- }, {
- "date": "2016-05-03",
- "name": "张晓明",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 13 弄",
- "tag": "南京小组"
-
- }, {
- "date": "2016-05-04",
- "name": "李米中",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 14 弄",
- "tag": "设计一所"
-
- }, {
- "date": "2016-05-05",
- "name": "向飒飒",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 15 弄",
- "tag": "南京小组"
-
- }, {
- "date": "2016-05-06",
- "name": "王小虎",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 16 弄",
- "tag": "设计三所"
-
- },
- {
- "date": "2016-05-07",
- "name": "张晓明",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 17 弄",
- "tag": "设计二所"
-
- }, {
- "date": "2016-05-08",
- "name": "李米中",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 18 弄",
- "tag": "南京小组"
-
- }, {
- "date": "2016-05-09",
- "name": "向飒飒",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 19 弄",
- "tag": "设计一所"
-
- }, {
- "date": "2016-05-10",
- "name": "王小虎",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 20 弄",
- "tag": "设计三所"
-
- },
- {
- "date": "2016-05-11",
- "name": "张晓明",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 21 弄",
- "tag": "设计三所"
-
- }, {
- "date": "2016-05-12",
- "name": "李米中",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 22 弄",
- "tag": "设计二所"
-
- }, {
- "date": "2016-05-13",
- "name": "向飒飒",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 23 弄",
- "tag": "南京小组"
-
- }, {
- "date": "2016-05-14",
- "name": "王小虎",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 24 弄",
- "tag": "设计一所"
-
- }, {
- "date": "2016-05-15",
- "name": "王小虎",
- "phone": "18852067999",
- "address": "上海市普陀区金沙江路 25 弄",
- "tag": "设计二所"
-
- }
- ]
- },
- {
- "sectorData": [{
- "itemid": 10001,
- "text": "设计一所",
- "value": "设计一所"
- }, {
- "itemid": 10002,
- "text": "设计二所",
- "value": "设计二所"
- },
- {
- "itemid": 10003,
- "text": "设计三所",
- "value": "设计三所"
- },
- {
- "itemid": 10004,
- "text": "南京小组",
- "value": "南京小组"
- }
- ]
- }
- ]
vue链接:vue
elementUI链接:elementUI
axios.js链接:axios.min.js
(1)在el-table中通过设置 type="expand" 和 Scoped slot
可以开启展开行功能,el-table-column
的模板会被渲染成为展开行的内容,展开行可访问的属性与使用自定义列模板时的 Scoped slot
相同。然后在表格的最后一列设置两个按钮,但是两个按钮要根据 v-if="scope.row.isSet"来进行“编辑和确定”的切换。
(2)在每条数据中设置一个isExpand="false"的属性,默认该行为未展开状态,当展开或关闭该行时,记录下该状态,如下:
/* 更改每一行的张开/关闭状态 */
expandChange(row, expandedRows) {
row.isExpand = !row.isExpand;
},
(3)在点击编辑按钮时,对其他行进行验证,如其他行存在编辑状态,则先保存对其他行的编辑,然后才能对该行进行编辑;点击改变某条数据变为可编辑状态,确认时,对数据进行非空校验。如下:
/* 开启编辑单元格 */
handleEdit(index, row, e) {
for (const i of this.tableData) {
if (!i.isSet) {
return this.$message.warning('请先保存当前编辑项');
}
}
if (!row.isExpand) {
//调用,table的方法,展开/折叠 行
this.$refs.refTable.toggleRowExpansion(row);
}
row.isSet = false;},
/* 保存单元格,进行编辑验证 */
saveEdit(index, row, column) {
// console.log(row);
if ((row.address.replace(/\s+/g, '') == '' || (row.phone.replace(/\s+/g, '') == ''))) {
row.isSet = false;
return this.$message.error('数据不能为空');
} else {
row.isSet = true;
}
//调用,table的方法,展开/折叠 行
this.$refs.refTable.toggleRowExpansion(row);
},
(4)分页展示的核心代码是在获取的数据后,写入到el-table中,如下红色部分:
<el-table ref="refTable" height="500" :data="tableData.slice((currentPage-1)*pagesize,currentPage*pagesize)"
style="width: 100%" @expand-change="expandChange">/* 分页方法 */
handleSizeChange(val) {
// console.log(`每页 ${val} 条`);
this.pagesize = val;
},
handleCurrentChange: function(val) {
// console.log(`当前页: ${val}`);
this.currentPage = val;
},
(5) 此案例中是对姓名中的关键字进行搜索,对字符串使用indexOf属性,对搜索到的数据添加到一个新的数组中,并返回给el-table;在筛选中,是element中的,可去案例中参考。如下:
<el-table-column prop="tag" label="部门" width="140" :filters="sectorData" :filter-method="filterTag">
<template slot-scope="scope">
<el-tag size="medium" disable-transitions>{{scope.row.tag}}</el-tag>
</template>
</el-table-column><template slot="header" slot-scope="scope">
<el-input clearable v-model="search" prefix-icon="el-icon-search" size="mini" placeholder="输入姓名关键字搜索" @input="searchName" />
</template>/* 部门筛选 */
filterTag(value, row, column) {
console.log(value);
// console.log(row);
return row.tag === value;
},/* 姓名关键字搜索 */
searchName(search) {
var newList = [];
// console.log(search);
if (search != '') {
vm.oldtableData.forEach(item => {
if (item.name.indexOf(search) != -1) {
//空字符串包含在所有字符串中,因此控制会返回所有列表
newList.push(item);
}
});
return this.tableData = newList;
} else {
return this.tableData = this.oldtableData;
}
},
(6)下面就是对保存和提交的简单校验,在提交时要确认数据已经保存,保存的数据不可再编辑
/* 提交表单 */
postForm() {
if (!this.btnDisabled) {
return this.$message.error('请先保存');
} else {
this.$confirm('是否提交?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then((action) => {
this.$message({
type: 'success',
message: '提交成功!',});
if (action === 'confirm') {
//提交表单
console.log(this.tableData);
}
}).catch(() => {
this.$message({
type: 'info',
message: '已取消提交!'
});
});
}
},
/* 保存表单 */
saveForm() {
for (var i = 0; i < this.tableData.length; i++) {
if (!this.tableData[i].isSet) {
this.$message.warning('请先保存当前编辑项');
return this.btnDisabled = false;
} else {
this.btnDisabled = true;
}
}
},
/* 撤回保存 */
backtrack() {
this.btnDisabled = false;
},
这次vue小实例就写到这,如果内容、代码有不妥的地方,望斧正,谢谢。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。