zoukankan      html  css  js  c++  java
  • 关于bootstrap table 的可编辑列表的实例

      最近被安排到一个新的项目里,首先被分配了一个成果管理的模块,虽然是简单的增删改查,但是也费了不少功夫。

    其中耽误最长的时间就是form中嵌套了两个可编辑列表的子表。废话不说上干货 = =

    参考资料 1. http://bootstrap-table.wenzhixin.net.cn/documentation/ api

         2. http://blog.csdn.net/lzxadsl/article/details/49181127

    //2017.10.17补充相关版本的bootstrap及edit.js

    链接: https://pan.baidu.com/s/1gflGSW7 密码: ef5a


    20180913 更新链接 

     链接: https://pan.baidu.com/s/1vPdFzr3XL7QKkGGP5bk_aQ 密码: kq97

    界面图:

    jsp代码:

    简单的一个按钮和一个普通的table 

    <div class="my_table_bar">
                        <div class="col-xs-10 bar_title">
                            <p align="center">
                                <strong>成果的知识产权情况</strong>
                            </p>
                        </div>
                        <div class="col-xs-2 bar_option">
                            <a class="insert" href="javascript:addRow(2);" title="新增行">
                                <i class="glyphicon glyphicon-plus" id="editTable_add_kjcg"></i>
                                新增
                            </a>
                        </div>
                    </div>
                    <table id="reportTable2" class="table table-bordered table-hover"></table>

     js代码:

    /*
     * @param 主表ID
     * 加载可编辑列表公共方法*/
    function loadEditTable(pid){
        //重置table内数据
        $('#reportTable1').bootstrapTable('destroy');//这里必须要添加这个销毁,否则新增、修改、查看的切换可编辑列表中的数据可能加载出现问题。
        $('#reportTable2').bootstrapTable('destroy');
        
        $('#reportTable1').bootstrapTable({  
            method: 'get',
            url:contextPath + '/cggl/getHJQKTable.do?code='+pid,
            editable:true,//开启编辑模式  
            clickToSelect: true,
            cache : false,
            columns: [  
                {field:"JX_NAME",title:"所获奖项明称",align:"center",edit:{required:true,type:'text' }},  
                {field:"JX_ORG",title:"奖励单位",align:"center",edit:{type:'text' }},  
                {field:"JX_TIME",title:"奖励年度",align:"center",edit:{type:'text' }}, 
                {field:"JX_RANK",title:"授奖等级",align:"center",edit:{type:'text' }},
                {field:"operate",title:"操作",align:"center",formatter : operateFormatter1,edit:false}
            ],
            onEditableHidden: function(field, row, $el, reason) { // 当编辑状态被隐藏时触发
                if(reason === 'save') {
                    var $td = $el.closest('tr').children();
                    $td.eq(-1).html((row.price*row.number).toFixed(2));
                    $el.closest('tr').next().find('.editable').editable('show'); //编辑状态向下一行移动
                } else if(reason === 'nochange') {
                    $el.closest('tr').next().find('.editable').editable('show');
                }
            },
            onEditableSave: function (field, row, oldValue, $el) {
                  $table = $('#reportTable1').bootstrapTable({});
                  $table.bootstrapTable('updateRow', {index: row.rowId, row: row});
            }
        });
        
        $('#reportTable2').bootstrapTable({  
            method: 'get',
            url:contextPath + '/cggl/getZscqTable.do?code='+pid,
            editable:true,//开启编辑模式  
            clickToSelect: true,  
            cache : false,
            columns: [  
                {field:"ZSCQ_XS",title:"知识产权形式",align:"center",edit:{required:true ,type:'text'}},  
                {field:"ZSCQ_NAME",title:"所获知识产权项目名称",align:"center",edit:{type:'text'}},  
                {field:"ZSCQ_CODE",title:"知识产权号",align:"center",edit:{type:'text'}},  
                {field:"ZSCQ_TIME",title:"授权时间",align:"center",edit:{type:'text'}},
                {field:"operate",title:"操作",align:"center",formatter : operateFormatter2,edit:false} 
            ],
            onEditableSave: function (field, row, oldValue, $el) {
                  $table = $('#reportTable1').bootstrapTable({});
                  $table.bootstrapTable('updateRow', {index: row.rowId, row: row});
            }
        });  
        
    }

    PS:上面提到的destroy方法,如果不加的话,很多时候可编辑列表都是直接调用的缓存中的数据。举个例子,就是我先打开新增,可编辑列表中是没有数据的,再打开修改的话,可编辑列表同样会没有数据,很奇怪,但是具体的原因我也没有找到,ajax 中 cache也已经设置成了false。头大

    java代码:

    其实我感觉后台是没必要贴的,但是想想我在查阅资料的时候,网上找的资料大多数不全,所以换位思考下,我就全贴出来了。

    这里有一个点就是我先把主表保存了,返回了插入数据的ID,然后用这个ID作为外键,将子表数据新增。

    其他的话,修改我是先删除ID关联的子表所有数据,然后再新增。(这里如果有更好的方法记得@我,谢谢大神)

        /**
         * 新增
         * 包括对成果获奖情况和知识产权情况的保存
         */
        @SuppressWarnings("rawtypes")
        @RequestMapping("/add.do")
        public void addToCggl() {
            HttpServletRequest request = getRequest();
            HttpServletResponse response = getResponse();
    
            try {
                // 全路径对象或者表名
                String className = request.getParameter(OBJECTID_PARAMETER).trim();
                //获取对应的子表数据
                String hjqk = request.getParameter("hjqk").trim();
                String zscq = request.getParameter("zscq").trim();
                
                // JDBC处理方式
                Map entityValue = assembleParameterMap(request.getParameterMap());
                entityValue.remove("objectId");
                //将子表数据移除
                entityValue.remove("hjqk");
                entityValue.remove("zscq");
                
                jdbcService.saveCommonObject(className, entityValue);
                String parentID = entityValue.get("ID").toString();
                
                
                //调用子表的保存方法
                saveEditTable(parentID,hjqk,zscq);
                
                String msg = MsgUtil.getI18NTipMessage(CoreTipDefine.ADDT_0001);
                commonResult(response, true, msg);
            } catch (Exception e) {
                e.printStackTrace();
                String msg = MsgUtil.getI18NExpMessage(e);
                commonResult(response, false, msg);
            }
        }

    子表传过来的值是json字符串。下面就是在java中对json字符串的转换,因为字段不多,所以也没用Gson。

        List<Map<String, String>> list = new ArrayList<Map<String, String>>();
            List<Map<String, String>> list1 = new ArrayList<Map<String, String>>();
    
            // 首先把字符串转成 JSONArray 对象
            JSONArray json = JSONArray.fromObject(hjqk);
            JSONArray json1 = JSONArray.fromObject(zscq);
    
            if (json.size() > 0) {
                for (int i = 0; i < json.size(); i++) {
                    JSONObject job = json.getJSONObject(i); // 遍历 jsonarray
                                                            // 数组,把每一个对象转成 json 对象
                    Map<String, String> map = new HashMap<String, String>();
    
                    // 得到 每个对象中的属性值
                    map.put("CG_ID", code);
                    map.put("JX_NAME", job.get("JX_NAME").toString());
                    map.put("JX_ORG", job.get("JX_ORG").toString());
                    map.put("JX_TIME", job.get("JX_TIME").toString());
                    map.put("JX_RANK", job.get("JX_RANK").toString());
                    map.put("id", UUIDGenerator.generateUUID());
    
                    list.add(map);
                }
            }

     最后是bootstrap-table-edit.js 

    /**
     * 可编辑表格插件
     * 如果编辑表格中有用到,下拉框和日期,必须先引入 
     * bootstrap-select 和 bootstrap-datetimepicker两个控件
     * @author lizx <851697971@qq.com>
     * @version 1.0
     * @date 2015-10-13
     */
    
    (function($){
        'use strict';
    
        $.extend($.fn.bootstrapTable.defaults, {
            editable: false
        });
        
        var BootstrapTable = $.fn.bootstrapTable.Constructor,
            _init = BootstrapTable.prototype.init,
            _initBody = BootstrapTable.prototype.initBody,
            _onSort = BootstrapTable.prototype.onSort,
            _append = BootstrapTable.prototype.append,
            _initHeader = BootstrapTable.prototype.initHeader ;
        //添加编辑表格默认属性,如何edit设置为false时,表示该列不可编辑
        $.extend(true,BootstrapTable.COLUMN_DEFAULTS,{
            edit:{
                type:'text'//目前只支持 文本:text 下拉:select 日期:date 
            }
         });
        BootstrapTable.prototype.init = function () {
            _init.apply(this, Array.prototype.slice.apply(arguments));
            var that = this;
            that.prevEditRow = null;//上一次编辑的行
            that.columns = {};//列配置信息
            that.insertRowVal = {};//新插入行的默认值
            that.enableAppend = true;//允许添加新行
            if (that.options.editable) {
                var columnObj = this['getColumns']();
                $.each(columnObj,function(i,obj){
                    $.each(obj,function(z,col){
                        if(!isNaN(col.fieldIndex) && col.fieldIndex >= 0){
                            if(col.checkbox)col.edit = false;
                            that.columns['column'+col.fieldIndex] = col;
                            that.insertRowVal[col.field] = '';
                        }
                    });
                });
                //this.initEdit();
            }
        };
        /*BootstrapTable.prototype.initHeader = function(){
            _initHeader.apply(this, Array.prototype.slice.apply(arguments));
            this.$container.find('.fixed-table-header').addClass('success');
        };*/
        BootstrapTable.prototype.initBody = function () {
            var that = this;
            
            _initBody.apply(this, Array.prototype.slice.apply(arguments));
            if (!that.options.editable) return;
            this.initEdit();
            
            //如果列是下拉框,则转换值为对应的文本
            $.each(that.columns,function(indx,col){
                if(col.edit && col.edit.type == 'select'){
                    col.edit = $.extend({},$.fn.bootstrapSelect.defaults,col.edit);
                    if(col.edit.data.length > 0){
                        that.$body.find('>tr').each(function(){
                            if(that.getData().length < 1)return true;
                            var rowData = that.data[$(this).data('index')];//当前点击td所在行的数据
                            var $td = $(this).find('td').eq(col.fieldIndex);
                            $.each(col.edit.data,function(i,data){
                                if(data[col.edit.valueField] == rowData[col.field]){
                                    $td.html(data[col.edit.textField]);
                                }
                            });
                        });
                    }
                    else if(col.edit.url){
                        $.ajax({
                            url:col.edit.url,
                            type:'post',
                            data:col.edit.paramsType == 'json' ? JSON.stringify(col.edit.params) : col.edit.params,
                            dataType:'json',
                            success: function(jsonLst) {
                                col.edit.onLoadSuccess.call(this,jsonLst);
                                that.$body.find('>tr').each(function(){
                                    if(that.getData().length < 1)return true;
                                    var rowData = that.data[$(this).data('index')];//当前点击td所在行的数据
                                    var $td = $(this).find('td').eq(col.fieldIndex);
                                    $.each(jsonLst,function(i,data){
                                        if(data[col.edit.valueField] == rowData[col.field]){
                                            $td.html(data[col.edit.textField]);
                                        }
                                    });
                                });
                                col.edit.data = jsonLst;
                                col.edit.url = null;
                            },
                            error: function(xhr, textStatus, errorThrown){
                                col.edit.onLoadError.call(this);
                                col.edit.data = [];
                                col.edit.url = null;
                                throw col.field+' 列下拉框数据加载失败';
                            }
                        });
                    }
                }
            });
        };
        //根据行号删除指定行
        BootstrapTable.prototype.removeRow = function (rowNum) {
            var that = this;
            var len = that.options.data.length;
            if (isNaN(rowNum)){
                return;
            }
            if(that.$body.find('.editable-select').data('index') != rowNum){
                recover(that);
            }
            //删除数据
            that.options.data.splice(rowNum,1);
            if (len === that.options.data.length){
                return;
            }
            var oldClass = {};//保存被标记修改的样式
            that.$body.find('>tr').each(function(indx){
                if($(this).hasClass('editable-modify')){
                    if(indx > rowNum){
                        oldClass[indx-1] = 'editable-modify';
                    }
                    else{
                        oldClass[indx] = 'editable-modify';
                    }
                }
            });
            //this.prevEditRow = null;
            //this.$body.find('>tr').removeClass('editable-select');
            that.initBody();
            //将标记改变过行的样式从新设置回去
            for(var key in oldClass){
                that.$body.find('>tr').eq(key).addClass(oldClass[key]);
            }
            //this.initEdit();
            //没有数据时给提示加上样式
            if(that.getData().length < 1){
                that.$body.find('>tr').addClass('no-records-found');
            }
        };
        BootstrapTable.prototype.append = function (){
            var that = this;
            //if(!that.enableAppend)return;
            var oldClass = {};//保存被标记修改的样式
            that.$body.find('>tr').each(function(indx){
                if($(this).hasClass('editable-modify') || $(this).hasClass('editable-insert')){
                    oldClass[indx] = 'editable-modify';
                }
            });
            arguments[0] = $.extend({},that.insertRowVal,arguments[0]);
            _append.apply(this,Array.prototype.slice.apply(arguments));
            if (that.options.editable){
                //that.initEdit();
                setTimeout(function (){
                    //将标记改变过行的样式从新设置回去
                    for(var key in oldClass){
                        that.$body.find('>tr').eq(key).addClass(oldClass[key]);
                    }
                    that.$body.find('>tr:last').addClass('editable-modify');
                    that.$body.find('>tr:last').addClass('editable-insert');//双重保险,防止在快速点击添加时,为给新增行设置editable-modify属性
                    that.$body.find('>tr:last').click();
                },60);
            }
            
        };
        
        BootstrapTable.prototype.onSort = function () {
            _onSort.apply(this, Array.prototype.slice.apply(arguments));
            var that = this;
            if (that.options.editable) {
                this.initEdit();
            }
        };
        BootstrapTable.prototype.getData = function () {
            return (this.searchText || this.searchCallback) ? this.data : this.options.data;
        };
        //获取全部的数据
        BootstrapTable.prototype.getAllData = function () {
            return this.options.data;
        };
    
        BootstrapTable.prototype.getColumns = function () {
            return this.options.columns;
        };
        /**
         * 获取有被修改过行的值
         */
        BootstrapTable.prototype.getModiDatas = function (){
            var that = this;
            var datas = [];
            that.$body.find('.editable-modify').each(function(){
                if(that.data[$(this).data('index')]){
                    datas.push(that.data[$(this).data('index')]);
                }
            });
            return datas;
        };
    
        /**
         * 获取指定列的和,参数为列下标
         */
        BootstrapTable.prototype.getColTotal = function (num){
            var retVal = 0;
            this.$body.find('>tr').each(function(){
                var colNum = 0;
                if($(this).hasClass('editable-select')){
                    colNum = $(this).find('td').eq(num).find('input').val();
                }
                else{
                    colNum = $(this).find('td').eq(num).html();
                }
                
                if(!isNaN(colNum)){//是数字才做想加
                    retVal += Number(colNum);
                }
            });
            return retVal;
        };
        
        /**
         * 创建可编辑表格
         */
        BootstrapTable.prototype.initEdit = function(){
            var that = this,
            data = this.getData();
            //this.$body.find('> tr').unbind('click').on('click'
            //this.$body.delegate('>tr','click'
            this.$body.find('> tr').unbind('click').on('click',function(){
                var $tr = $(this);
                if($tr.hasClass('editable-select') || data.length < 1 || $tr.hasClass('no-records-found')){
                    return;
                }
                $tr.removeClass('no-records-found');
                recover(that);
                that.prevEditRow = $tr;
                $tr.addClass('editable-select');//给当前编辑行添加样式,目前样式为空只做标识使用
                that.$body.find('> tr').not(this).removeClass('editable-select');
                $tr.find('td').closest('td').siblings().html(function(i,html){
                    initTrClick(that,this);
                });
            });
            //鼠标点击事件
            $(document).bind('mousedown',function(event){
                var $target = $(event.target);
                if(!($target.parents().andSelf().is(that.$body)) && !($target.parents().andSelf().is($('.datetimepicker')))){
                    setTimeout(function () {
                        recover(that);
                        //that.prevEditRow = null;
                        //that.$body.find('> tr').removeClass('editable-select');
                    },10);
                };
            });
            
        };
        
        $.fn.bootstrapTable.methods.push('getColumns',
            'getModiDatas','removeRow','getColTotal','getAllData');
        
        /**
         * 给tr添加点击事件
         */
        function initTrClick(that,_this){
            that.enableAppend = true;
            var $td = $(_this);
            var $tr = $td.parent();
            var rowData = that.data[$tr.data('index')];//当前点击td所在行的数据
            var tdIndex = $tr.children().index($td);//当前点击的td下标
            var tdOpt = that.columns['column'+tdIndex];
            if(rowData.IS_TYPING!="0"&&rowData.IS_TYPING!="2"){//判断接口取数方式
            if(!tdOpt.edit || typeof tdOpt.edit != 'object'){
                return ;
            }
            $td.data('field',tdOpt.field);
            if(!$td.data('oldVal')){
                $td.data('oldVal',$.trim(rowData[tdOpt.field]));
            }
            var height = $td.innerHeight() - 3;
            var width = $td.innerWidth() - 2;
            $td.data('style',$td.attr('style'));//保存原来的样式
            $td.attr('style','margin:0px;padding:1px!important;');
            var placeholder = '';
            if(tdOpt.edit.required == true){
                placeholder = '必填项';
            }
            var value = rowData[tdOpt.field] == null || rowData[tdOpt.field] == ''?'':rowData[tdOpt.field];
            $td.html('<div style="margin:0;padding:0;overflow:hidden;border:solid 0px red;height:'+(height)+'px;'+(width)+'px;">'
                        +'<input type="text" placeholder="'+placeholder+'" value="'+value+'" style="margin-left: 0px; margin-right: 0px; padding-top: 1px; padding-bottom: 1px; 100%;height:100%">'
                    +'</div>');
            $td.width(width);
            var $input = $td.find('input');
            if(!tdOpt.edit.type || tdOpt.edit.type == 'text'){
                if(tdOpt.edit['click'] && typeof tdOpt.edit['click'] === 'function'){
                    $input.unbind('click').bind('click',function(event){
                        tdOpt.edit['click'].call(this,event);
                    });
                }
                if(tdOpt.edit['focus'] && typeof tdOpt.edit['focus'] === 'function'){
                    $input.unbind('focus').bind('focus',function(event){
                        tdOpt.edit['focus'].call(this,event);
                    });
                }
                $input.unbind('blur').on('blur',function(event){
                    if(tdOpt.edit['blur'] && typeof tdOpt.edit['blur'] === 'function'){
                        tdOpt.edit['blur'].call(this,event);
                    }
                });
                /*$input.unbind('keyup').on('keyup',function(event){
                    debugger;
                    var reg=new RegExp("/[^d{1,}.-d{1,}|d{1,}]/g");
                    if(!reg.test($input.val())){
                        $input.val($input.val().replace(/[^d{1,}.-d{1,}|d{1,}]/g, ""));
                    }
                });*/
                
            }
            else if(tdOpt.edit.type == 'select'){
                $input.bootstrapSelect(tdOpt.edit);
            }
            else if(tdOpt.edit.type == 'date'){
                $td.html('<div style="margin:0;padding:0;overflow:hidden;border:solid 0px red;height:'+(height)+'px;'+(width)+'px;" class="input-group date form_datetime" data-link-field="dtp_editable_input">'
                            +'<input class="form-control" type="text" value="'+value+'">'
                            +'<span class="input-group-addon"><span class="glyphicon glyphicon-th"></span></span>'
                        +'</div>'
                        +'<input type="hidden" id="dtp_editable_input" value="'+value+'"/>'
                );
                that.$body.find('.form_datetime').datetimepicker({
                    weekStart: 1,
                    todayBtn:  1,
                    autoclose: 1,
                    todayHighlight: 1,
                    startView: 2,
                    forceParse: 0,
                    language:'zh-CN',
                    format: 'yyyy-mm-dd hh:ii:ss',
                    pickerPosition: 'bottom-left',
                    showMeridian: 1
                });
            }
            }else{
                return;
            }
        }
        /**
         * 恢复tr,使之处于不可编辑状态
         */
        function recover(that){
            var isModi = false;//判断行值是否变动过
            if(that.prevEditRow != null){
                that.prevEditRow.find('td').closest('td').siblings().html(function(i,html){
                    $(this).attr('style',$(this).data('style'));
                    var textVal = $(this).find('input[type="text"]').val();
                    var hiddenVal = $(this).find('input[type="hidden"]').val();
    //                if(typeof $(this).find('input[type="text"]').bootstrapSelect('getText') != 'object'){
                    if(typeof $(this).find('input[type="text"]') != 'object'){
                        $(this).find('input[type="text"]').bootstrapSelect('destroy');
                    }
                    
                    if(textVal != undefined){
                        if($(this).data('oldVal') != (hiddenVal?hiddenVal:$.trim(textVal)) && $(this).data('field')) {
                            that.data[that.prevEditRow.data('index')][$(this).data('field')] = hiddenVal?hiddenVal:$.trim(textVal);
                            isModi = true;
                        }
                        if(that.columns['column'+i].edit.required == true){
                            if(textVal == null || textVal == ''){
                                that.enableAppend = false;
                                return '<span style="color:red;">必填项不能为空</span>';
                            }
                        }
                        return $.trim(textVal);
                    }
                });
                //新值跟旧值不匹配证明被改过
                if(isModi || that.prevEditRow.hasClass('editable-insert')){
                    that.prevEditRow.addClass('editable-modify');
                }
                else{
                    that.prevEditRow.removeClass('editable-modify');
                }
                that.prevEditRow = null;
                that.$body.find('> tr').removeClass('editable-select');
            }
        }
        
    })(jQuery);

    2017/08/03

    对新增,删除调用方法的补充

    function operateFormatter1(value, row, index) {
        return [
          "<a class="remove" href='javascript:removeRow("+index+",1)' title="删除改行">",
          "<i class='glyphicon glyphicon-remove'></i>",
          "</a>     "
        ].join('');
      }
    function operateFormatter2(value, row, index) {
        return [
          "<a class="remove" href='javascript:removeRow("+index+",2)' title="删除改行">",
          "<i class='glyphicon glyphicon-remove'></i>",
          "</a>     "
        ].join('');
      }
    
    $('#reportTable1','#reportTable2').on( 'click', 'td:has(.editable)', function (e) {
        //e.preventDefault();
        e.stopPropagation(); // 阻止事件的冒泡行为
       $(this).find('.editable').editable('show'); // 打开被点击单元格的编辑状态
    } );
    
    //可编辑列表新增一行
    function addRow(mark){
        var rows = [];
        
        //通过mark来判断为哪个可编辑框创建新一行
        if(mark == 1){
             $('#reportTable1').bootstrapTable('append',rows);
        }else if(mark == 2){
            $('#reportTable2').bootstrapTable('append',rows);
        }
       
    }
    //删除指定行
    function removeRow(deleteIndex,mark){
        if(mark == "1"){
            $('#reportTable1').bootstrapTable('removeRow', deleteIndex);
        }else if(mark == "2"){
            $('#reportTable2').bootstrapTable('removeRow', deleteIndex);
        }
    }

    好了,基本就是这些。

  • 相关阅读:
    美联储主席和欧洲央行说了什么
    12月CPI,PPI有哪些变化
    中国人民银行行长易纲就贯彻落实中央经济工作会议精神接受采访谈
    2018年个人的一些简单预测
    从首套房利率走势看市场
    百城价格房价周期和郑州、武汉房价比较分析
    国际非农超预期美联储主席态度软化,国内适度宽松货币+积极财政仍是主基调
    三大经济体年2018年末形势一览
    从房地产住宅销售面积增速看房地产行业
    枚举类
  • 原文地址:https://www.cnblogs.com/chuanqiMa/p/6895064.html
Copyright © 2011-2022 走看看