前言:项目需求写个表格带新增删除,看了下项目原本使用的是jq+bootstrap+layui的一个组合,我的页面基本是用layui完成的,layui也有自己的table组件,官方文档很详细,所以第一版的时候是用的layui,但是写到一半的时候出了问题,在以往的项目中通常新增是用弹窗的形式将要新增的内容写入,再push到table的data数组中,此次需求是在表格里每行带input以及下拉选项框,layui有个坑是超出部分会直接隐藏,所以就没法选择下拉框,只好半途改用bootstrap-table这个组件,由于官方文档是英文的,看api费了点劲,所以就本次找资料跟踩过的坑做下总结!

 

这个是根据需求另外做的一个例子,就是点击新增就出来一个空白行,可以输入也可以选择下拉选项,废话不多说,我们开搞!

先把准备工作做好,引入css与js文件,

<--css---> 

<link rel="stylesheet" href="./bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="./bootstrap-table/bootstrap-table.min.css">

<--js---> 
<script src="https://code.jquery/jquery-3.3.1.min.js"></script>
<script src="./bootstrap/js/bootstrap.min.js"></script>
<script src="./bootstrap-table/bootstrap-table.js"></script>

HTML部分:


        <table id="table"></table>

        <button id="addBtn" onclick="add()">增加</button>

        <button onclick="getTab()">获取</button>

通过id来绑定table实例,

JS部分,生成table实例:

$('#table').bootstrapTable({
            columns: [{
                field: 'id',
                title: 'ID',
                formatter:idForm,
                width:'25%'
            }, {
                field: 'name',
                title: '名字',
                width:'25%',
                formatter:nameForm,
            }, {
                field: 'price',
                title: '价格',
                width:'25%',
                formatter:priceForm
            }, {
                field:'id',
                title: '操作',
                width:'25%',
                formatter:doSome
            },],
            data:[]
        });

bootstrap-table是通过formatter属性来返回函数格式化指定单元格的内容,可以添加html标签,所以通过这一属性来添加input框与select

//input输入框
        function priceForm(value,row,index){
            return ['<input type="text" id="1plan'+row.id+'" data='+value+' value='+value+' onblur="addTarget('+row.id+',1)">'].join("")
        }
//下拉列表
        function nameForm(value,row,index){
            return `
                    <select id="sele`+ row.id +`" onchange="selectchange(`+ row.id +`)" class="ss">
                        <option value="1">item1</option>
                        <option value="2">item2</option>
                        <option value="3">item3</option>
                        <option value="4">item4</option>
                    </select>
                `
        }

这样基本的表单结构就出来了,点击添加是通过bootstrap-table自有的方法insertRow来实现

function add(){
            var count = $('#table').bootstrapTable('getData').length;

            
            $('#table').bootstrapTable('insertRow',{index:count,row: {
                id:count+1,
                name:'',
                price:'2'
            }});

        }

接下来就谈下中间遇到的俩坑,这个涉及到改变单元格对应value,input中的值修改后需要通过bootstrap-table自带的方法的updateCell来修改对应表格中的值,我在这边用的方法是在新建行时就拼接了这条input的id对应的当前行的id值,所以再修改时遍历行内数据,找到对应该id的一条,再修改指定的值即可,这个是根据https://blog.csdn/LLL_liuhui/article/details/82256509这个博客上的方法copy来的

//id:这条数据的id  type :1,2,3:代表的是第几个目标值
    function addTarget(id,type){
        var writevalue=$("#"+type+"plan"+id).val(); //获取改变后的输入框的值
        var oldvalue = $("#"+type+"plan"+id).attr("data"); //获取输入框原本的值
        
        if(!(writevalue==oldvalue)){//通过判断输入框的值是否改变,是否写入jsontarget改变的json数据
            oldvalue=writevalue;
            $("#"+type+"plan"+id).attr("data",oldvalue);
            writeJson(id,type,writevalue);
        }

    }

    //修改指定单元格值
    function writeJson(id,type,writevalue){
        var counts = $('#table').bootstrapTable('getData');

        for(var i = 0;i<counts.length;i++){
            if(counts[i].id == id){
                $('#table').bootstrapTable('updateCell',{
                    index:i,
                    field:'price',
                    value:writevalue
                })
            }
        }
    }

原本下拉框改变值也想根据这个思路来,但是遇到了俩坑,一个是在每次新增一行时(insertRow)会之前几行选择的会被清空,还有就是点击select的选项option,点了但是依然显示的是默认第一个,这个让我百思不得其解

BootstrapTable.prototype.insertRow = function (params) {
        if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) {
            return;
        }
        this.options.data.splice(params.index, 0, params.row);
        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
    };

找了好多网上资料,看到另一位写的博客http://wwwblogs/dandelZH/p/10171684.html,才知道这坑来源于bootstrap-table底层源码,这个是insertRow的方法源码,就是在你每新增一行的时候,他会调用 this.initSearch(),遍历当前表格内的数据,也会重新格式化一遍你的表格,同样的updateCell方法也是在最后调用该方法,那么就是在你每次调用到这些方法后你的表格显示的是格式化后即默认的没有任何选中的select值

BootstrapTable.prototype.insertRow = function (params) {
        if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) {
            return;
        }
        this.options.data.splice(params.index, 0, params.row);
        this.initSearch();
        this.initPagination();
        this.initSort();
        this.initBody(true);
    };

其实如果通过控制台打印table的数据,可以看到,每次updateCell后的值都是有更改成功的,我实际需要做的就是写个方法,在表格格式化后,我再遍历一遍数据,将每行的value与select中的option的值做比对,将与value值一致的option添加checked属性就行了

function reloadSlect(){
            //将表内数据遍历,在数据修改导致重置后,遍历和表内数据,
            //重新修改option的selected属性
            var counts = $('#table').bootstrapTable('getData');

            counts.forEach(function(item){

                var options = $("#sele"+ item.id + " option");
                var name = item.name;
                for(var j = 0;j<options.length;j++){
                    options.eq(j).removeAttr("selected");
                    if(options.eq(j).val() == name){
                        options.eq(j).attr("selected","selected");
                    }
                }
            })

        }

然后在会格式化表格的方法最后加上reloadSlect()调用就可以达到视觉上需要的效果。

 

为解决该问题参考的资料:

Bootstrap Table API 中文版(完整翻译文档)

bootstrap-table的一些基本使用及表内编辑的实现

Bootstrap-table 使用总结

更多推荐

bootstrap-table 增删以及嵌套input与select下拉框