效果展示
需要导入layui依赖 layui.js layui.css
具体使用可参考layui官方文档
https://www.layui.com/doc/modules/table.html
编码实现
<!DOCTYPE html>
<html lang="zh-Hans-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width" />
<meta name="author" content="www.akieay.com"/>
<meta name="robots" content="all"/>
<title>动态表单</title>
<link rel="stylesheet" href="../layui/css/layui.css">
<style>
/* 防止下拉框的下拉列表被隐藏---必须设置--- */
.layui-table-cell {
overflow: visible !important;
}
/* 设置下拉框的高度与表格单元相同 */
.layui-input, .layui-select, .layui-textarea{
height: 30px !important;
}
.layui-table-body,.layui-table-main {
height: 600px;
}
</style>
</head>
<body>
<div id="rrapp" v-cloak>
<form>
<table class="layui-table" id="formTable" lay-filter="cgform">
</table>
<div class="form-group">
<input type="button" class="btn btn-primary out" @click="printout" value="打印表单数据" />
</div>
</form>
</div>
<script type="text/html" id="toobarTable" desc="模板" >
<div class="layui-btn-group">
<a class="layui-btn" lay-event="add">添加表单项</a>
<a class="layui-btn" lay-event="clear">清空表单项</a>
<a class="layui-btn">(点击单元格可编辑)</a>
</div>
</script>
<script src="../js/common.js"></script>
<script src="../js/jquery.min.js"></script>
<script src="../js/vue.min.js"></script>
<script src="../layui/layui.js"></script>
<script src="../js/index.js"></script>
<style type="text/css">
.out{
width: 120px;
margin: 4px auto;
display: inherit;
height: 36px;
border-radius: 4px;
color: #7d5fb7;
font-size: 15px;
font-weight: 600;
}
.layui-table-body, .layui-table-main {
scrollbar-width: none;
-ms-overflow-style: none;
}
::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
</style>
</body>
</html>
var vm = new Vue({
el:'#rrapp',
//文本框类型数组
data:{
formItemTypes : [
{ name: '文本', value: 'W' },
{ name: '单选框', value: 'D' },
{ name: '复选框', value: 'F' },
{ name: '日期', value: 'R' },
{ name: '身份证', value: 'S' },
{ name: '电话', value: 'M'},
{ name: '单图', value: 'P' },
{ name: '多图', value: 'T'}
],
formData: [
],
},
methods: {
//打印表单数据
printout: function (event) {
console.log(vm.formData);
}
}
});
//监听表单事件
layui.use(['element','form'], function(){
var element = layui.element;
var form = layui.form;
var layer = layui.layer;
/**
* 监听表单select选择
* 通过过滤器【lay-filter】监听指定的select
* lay-filter="formtype"
*/
form.on('select(formtype)', function (data) {
//初始化时将表单类型下拉选择项的值 设置为rowId + "_" +类型type, 方便在修改表单项类型是赋值
var arr = data.value.split("_");
var rowId = parseInt(arr[0]), type = arr[1];
if(rowId > 0){
var list = vm.formData;
var data = null;
var delIndex = list.findIndex(item =>{
if(item.rowId == rowId){
data = item;
return item
}
})
data.type = type;
list.splice(delIndex, 1, data);
vm.formData = list;
}else{
alert("行ID错误")
}
});
});
//声明替换表单数据源的方法、修改动态表单时使用
var editFormTable;
layui.use('table', function(){
var table = layui.table;
//第一个实例
var tableIns = table.render({
elem: '#formTable',
id: 'formTable',
height: 500,
url: '../json/form.json', //数据接口
parseData: function(res) { //res 即为原始返回的数据
vm.formData = res.data;
return {
"code": res.code, //解析接口状态
"msg": res.msg, //解析提示文本
"count": res.count, //解析数据长度
"data": vm.formData //解析数据列表
};
},
page: false, //开启分页
toolbar: '#toobarTable', //头部工具栏
cols: [[ //表头
{field: 'order', title: '序号', width: 130, align: 'center', edit: 'number'},
{field: 'name', title: '栏名', width: 150, align: 'center', edit: 'text'},
{field: 'type', title: '类型', width: 200, align: 'center', unresize: true,
templet: function(row){
var list = vm.formItemTypes;
var str = '<select name="type" lay-filter="formtype">';
for(var i = 0; i < list.length; i++){
var item = list[i];
if(item.value == row.type){
str += '<option value="'+row.rowId+'_'+item.value+'" selected>'+item.name+'</option>';
}else{
str += '<option value="'+row.rowId+'_'+item.value+'">'+item.name+'</option>';
}
}
str += '</select>';
return str;
}
},
{field: 'value', title: '可选值(多项用,分隔)', width:400, align: 'center', edit: 'text'},
{field: 'required', title: '是否必填' ,width: 115, align: 'center',
templet: function(row){
var str = '<a lay-event="required">';
if(row.required == 'Y'){
str += '<input type="checkbox" name="required" checked lay-skin="switch" lay-text="是|否">';
}else if(row.required == 'N'){
str += '<input type="checkbox" name="required" lay-skin="switch" lay-text="是|否">';
}
str += '</a>';
return str;
}
},
{title: '操作', width: 185, align: 'center',
templet: function(row){
return '<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>'
}
}
]]
});
//使用指定的数据源替换原有的表单数据
editFormTable = function (formData){
tableIns.reload({
parseData: function() { //res 即为原始返回的数据
vm.formData = formData;
return {
"code": 0, //解析接口状态
"msg": '', //解析提示文本
"count": 0, //解析数据长度
"data": vm.formData //解析数据列表
};
},
});
}
/**
* 监听头部工具栏事件
* 注:toolbar是工具栏事件名【表示用于监听工具栏事件】,cgform是table原始容器的属性 lay-filter="对应的值"
* 使用示例, eg: lay-event="add" lay-event="clear"
*/
table.on('toolbar(cgform)', function(obj){
var data = obj.data //获得当前行数据
var layEvent = obj.event; //获得 lay-event 对应的值
// var tr = obj.tr; //获得当前行 tr 的 DOM 对象(如果有的话)
//获取事件名称
switch(layEvent){
case 'add':
var list = vm.formData;
var order = getMaxValue(list, 'order');
var rowId = getMaxValue(list, 'rowId');
var item = {
rowId: rowId,
order: order,
name: "user-0",
type: "W",
value: "",
required: "N"
};
list.push(item);
editFormTable(list);
break;
case 'clear':
editFormTable([]);
break;
};
});
//监听单元格编辑事件
table.on('edit(cgform)', function(obj){
var value = obj.value //得到修改后的值
,data = obj.data //得到所在行所有键值
,field = obj.field; //得到字段
if(field == "order"){
if(!checkIntegerNumber(value) || value.length > 5){
alert("序号请使用5位以内数字")
}
}
var list = vm.formData;
list = replace(list, data);
vm.formData = list;
});
/**
* 监听工具条【工具条与顶部工具栏不是同一个概念】
* 注:tool是工具条事件名【表示用于监听工具条事件】,cgform是table原始容器的属性 lay-filter="对应的值"
* 使用示例,eg: lay-event="required" lay-event="del"
*/
table.on('tool(cgform)', function (obj) {
var data = obj.data //获得当前行数据
, layEvent = obj.event; //获得 lay-event 对应的值
var tr = obj.tr; //获得当前行 tr 的 DOM 对象(如果有的话)
//监听到的事件操作标识
if (layEvent === 'del') {
layer.confirm('确定要删除该栏目吗?', function(index){
var list = vm.formData;
vm.formData = remove(list, data);
obj.del();
layer.close(index);
});
}else if(layEvent === 'required'){
if(data.required == 'Y'){
data.required = 'N';
}else if(data.required == 'N'){
data.required = 'Y';
}
var list = vm.formData;
vm.formData = replace(list, data);
}
});
});
//获取数组中最大的 排序号/行ID,
// type为'order'时获取最大排序号,type为'rowId'时获取最大行id
function getMaxValue(list, type) {
var num = 1;
if(list != null && list != undefined && list != [] && list.length > 0){
for(var i = 0; i < list.length; i++){
if(type == 'order'){
if(parseInt(list[i].order) >= num){
num = parseInt(list[i].order) + 1;
}
}else if(type == 'rowId'){
if(parseInt(list[i].rowId) >= num){
num = parseInt(list[i].rowId) + 1;
}
}
}
}
return num;
}
//根据唯一键值 更新数组中指定元素
function replace(list, data) {
for(var i = 0; i < list.length; i++){
if(list[i].rowId == data.rowId){
list[i] = data;
}
}
return list;
}
//根据唯一键值 删除数组中指定元素
function remove(arr, data) {
var result = [];
for(var i = 0; i < arr.length; i++){
if(arr[i].rowId != data.rowId){
result.push(arr[i]);
}
}
return result;
}
demo
下载地址: https://download.csdn.net/download/qq_39668819/12434066