使用Layui的数据表格与表单实现动态表单

效果展示

在这里插入图片描述

需要导入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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值