关于动态列的问题 #4

Closed
picong opened this Issue Jul 12, 2016 · 13 comments

Projects

None yet

5 participants

@picong
picong commented Jul 12, 2016

由于我要需要根据用户上传的excel文件中的数据展示到页面,虽然会规范上传的格式,但是这个格式也会有变化的,因此之前那些固定不变填列的key就可以了,现在貌似做不到,因为不知道到底用哪个格式,只能根据后台传入的List来生成表头和tbody,key是变化的,因此要求columns里面的参数也可以通过循环之类的来应用变化,表头的变化我自己通过js解决了,但是内容没办法,所以在这里希望大家帮帮忙。

@occultskyrong

贴点code?

@picong
picong commented Jul 18, 2016 edited

我之前的用datatables的code已经改为了通过ajax来获取数据然后动态生成列了,样式比较丑了。

$(function(){
    var dataId = $("#hideId").val();
    $.get("${ctx}/data/getBatchIds?dataId="+dataId,function(result){
        var batchIds = result.aaData;
        if(batchIds != null){
            var option = "";
            for(var i=0;i<batchIds.length;i++){
                if(batchIds.length>1){
                    if(i===0){
                        //默认显示最后一批次
                        option = "<option value='"+batchIds[i]+"' selected='selected'>第"+(batchIds.length)+"批次</option>";
                    }else{
                        option = "<option value='"+batchIds[i]+"'>第"+(batchIds.length-i)+"批次</option>";
                    }
                }else{
                    option = "<option value='"+batchIds[i]+"' selected='selected'>第"+(batchIds.length)+"批次</option>";
                }
                $("#batchId").append($(option));
            }
        }
        var batchId = $("#batchId").val();
        page(batchId);
    });

    $("#batchId").bind("change",function(){
        var batchId = $("#batchId").val();
        //切换批次时,需要去掉thead
        var $table = $("#records");
        $table.children("thead").remove();
        page(batchId);
    });

    function page(batchId){
        var num = 0;
        var pageSize = 10;
        function page(curr){
            $.getJSON("${ctx }/data/detail",{
                id : batchId,
                pageIndex: curr || 0,  
                pageSize: pageSize
            },function(result){
                parseHtml(result);
                laypage({
                    cont: ("page1"), //容器。值支持id名、原生dom对象,jquery对象。【如该容器为】:<div id="page1"></div>
                    pages: result.recordsTotal, //通过后台拿到的总页数
                    curr:curr || 0, //当前页
                    skin: 'molv',//皮肤颜色  
                    groups: 3, //连续显示分页数  
                    skip: true, //是否开启跳页  
                    first: '首页', //若不显示,设置false即可  
                    last: '尾页', //若不显示,设置false即可 
                    jump: function(obj, first){ //触发分页后的回调
                        if(!first){ //点击跳页触发函数自身,并传递当前页:obj.curr
                            page(obj.curr);
                        }
                    }
                }); 
            });
        };
        page();
        function parseHtml(result){
            num ++;
            var datas = result.aaData;
            var count = 0;
            var $table = $("#records");
            $table.children("tbody").remove();
             while($.isEmptyObject(datas[count].content)){
                count++;
            } 
            var obj=datas[count].content;
            var keys = Object.keys(obj);

            //根据keys来动态生成表头
            var $thead = $(
                    "<thead >"+
                    +"<tr id='head' height='19' class='xl65'"+
                    +"   class='text-c'>"+
                    +"</tr>"+
                    +"</thead>");
            for(var i=0;i<keys.length;i++){
                if(num === 1){
                var $th = $('<th class="xl65 text-c" style="white-space: nowrap;" x:str>'+keys[i]+'</th>');
                var $th2 = $('<th class="xl65 text-c" style="white-space: nowrap;" x:str>操作</th>');
                $thead.append($th);
                //头部只需要添加一次就够
                $table.append($thead);
                }
            }
            //添加操作一列
            $thead.append($th2);
             var dats = [];
             var ids = [];
             for(var i=0;i<datas.length;i++){
                 if(datas[i].content){
                    ids.push(datas[i].id);
                    dats.push(datas[i].content);
                 }
            } 
             var $tbody = $("<tbody class='text-c'></tbody>");
             for(var i=0;i<dats.length;i++){
                 if(dats != null){
                     var $tr = $(
                                '<tr  height="19" class="xl65"'
                                +'  style="height: 14.25pt; mso-height-source: userset; mso-height-alt: 285;" >'
                                +'</tr>'
                                );
                     for(j=0;j<keys.length;j++){
                         var value = dats[i][keys[j]];
                         var id = ids[i];
                         if(value !== undefined && id !== undefined){
                            var $td = '<td style="white-space: nowrap;" class="xl67 text-c" x:str>'+value+'</td>';
                         }else{
                             var $td = '<td style="white-space: nowrap;" class="xl67 text-c" x:str>'+""+'</td>'; 
                         }
                         $tr.append($td);
                     }
                        var $td2 = '<td width="100" class="xl67 text-c" x:str><a class="btn btn-primary radius" onClick="edit(\'编辑租户信息\',\'${ctx }/data/record/edit\',\''+id+'\')" href="javascript:;" title="编辑">编辑</a></td>';
                        $tr.append($td2);
                     $tbody.append($tr);
                 }
             }
             $table.append($tbody);
        }
    }

});

前面那些分页的逻辑,后面这个parseHtml(result)方法实现了动态生成表头,然后根据表头动态生成行。后台实际传来的东西我是存在了aaData中,按照老式的datatables的存法。样子虽然啊比较丑陋,但是功能实现了。下面是jsp,我js都写在那里面勒。
Uploading detail.txt…

@picong
picong commented Jul 18, 2016

希望datatables能够给出那种可以自己传入dom然后只帮生成样式的功能就可以了,可以统一样式嘛至少。哈哈 @occultskyrong

@occultskyrong

@picong 链接崩了。。。
应该可以吧,你自己去构造原始的table,dt只是把你的table进行加工,不过那种可能只能用前端分页了。。。。

@occultskyrong

@picong 其实根本的问题在于你这个是页面初始化的时候塞入不同的数据进行构造,还是需要上传excel后直接ajax数据。。。。

如果是上传excel后,数据会转存到数据库中,这样就直接用后端分页就可以直接用dt自带的data source去加载数据。。。
如果上传excel后,直接显示数据,就需要页面重绘,使用dt的api提供的data方法将数据依次按行写入。
data()-Get the data for the whole table.可以看下这个

@occultskyrong

@picong 不知道是否理解你的问题所在。。。。

@ssy341
Owner
ssy341 commented Jul 19, 2016 edited

我理解的动态列就是在dt初始化的时候不确定列的多少,即columns里的内容是根据实际操作变化而变化,在这个前提下,我做了一个简单的实例,希望帮助到大家,看下面代码:

<div class="container">
    <!--table里不需要写th-->
    <table id="example" class="table table-striped table-bordered">
    </table>
</div>
    var table;
    var colunmsStr = "name,position,salary,start_date,office,extn";
    var columsName = {
        "name": "姓名",
        "position": "位置",
        "salary": "薪水",
        "start_date": "开始时间",
        "office": "办公",
        "extn": "其他"
    };
    $(function () {
        getAllColumnsName();

        $("#rebulidTable").click(function () {
            var columnArr = $("input[name='allColumns']:checked");
            var columnStrIn = "";

            var columnsArray = [];

            //动态组装列
            $(columnArr).each(function (i, o) {
                var json = {data: null, title: null};
                o = $(o);
                columnStrIn += o.val();
                if (i != columnArr.length - 1) {
                    columnStrIn += ",";
                }
                json.data = o.val();
                json.title = columsName[o.val()];
                columnsArray.push(json);
            });
            colunmsStr = columnStrIn;

            //改变列的结构,先销毁前面的实例
            table.destroy();
            // 列改变了,需要清空table
            $("#example").empty();
            table = createTable(columnsArray);
        });



        //第一次初始化,加载所有列
        var columns = [
            {"data": "name", "title": columsName["name"]},
            {"data": "position", "title": columsName["position"]},
            {"data": "salary", "title": columsName["salary"]},
            {"data": "start_date", "title": columsName["start_date"]},
            {"data": "office", "title": columsName["office"]},
            {"data": "extn", "title": columsName["extn"]}
        ];
        table = createTable(columns);
    });

    function getAllColumnsName(){
        $.ajax({
            "url": "/loadAllColumns.jsp",
            "success": function (data) {
                data = JSON.parse(data);
                for (var i = 0; i < data.data.length; i++) {
                    var li = data.data[i];
                    $("#dynamicColumns").append("<li><input type='checkbox' checked name='allColumns' value='" + li + "'/>" + li + "</li>")
                }
            }
        });
    }

    //公共方法,多次初始化调用
    function createTable(columns) {
        return $("#example").DataTable({
            ajax: {
                url: "/dynamicColumns.jsp",
                data: {
                    "cols": colunmsStr
                }
            },
            //因为需要多次初始化,所以需要设置允许销毁实例
            "destroy": true,
            //列的配置信息通过变量传进来
            "columns": columns,
            "language": {
                "lengthMenu": "每页_MENU_ 条记录",
                "zeroRecords": "没有找到记录",
                "info": "第 _PAGE_ 页 ( 总共 _PAGES_ 页 )",
                "infoEmpty": "无记录",
                "search": "搜索:",
                "infoFiltered": "(从 _MAX_ 条记录过滤)",
                "paginate": {
                    "previous": "上一页",
                    "next": "下一页"
                }
            },
            "dom": "<'row'<'col-xs-2'l><'#mytool.col-xs-4'><'col-xs-6'f>r>" +
            "t" +
            "<'row'<'col-xs-6'i><'col-xs-6'p>>"
        });
    }

效果图如下:
demo4

🔴完整工程代码

顺便贴上官方讨论动态列的issue,看作者的意思,应该是把动态列加入到开发计划中,具体什么时候推出还不清楚,期待吧
#273

@occultskyrong
occultskyrong commented Jul 19, 2016 edited

@ssy341 我想了一下,你这个应该叫做“动态显示列”。。。

因为你已经获得了完整的表结构,要做的只是根据用户的选择(checkbox、select之类)进行列的显示和隐藏。
而后端动态列,是你完全不知道表结构,dt里面的ajax回传过来的数据直接是array数据,此时columns中无法获得具体的table的表结构,从而无法向{title:?,value:?}中塞入对应的数据key。。。

所以问题应该是如何在ajax获取到数据后,能将array中object的key:value关系传递给columns中。

@ssy341
Owner
ssy341 commented Jul 20, 2016

@occultskyrong 我觉得是类似的,我是模拟这个情况,关于表格的列,你可以通过ajax获取到,展示给前台,必须要有一个主动。比方说,表格本不知道要显示那些列,那么colums里需要什么也不知道,但是至少的前提,你知道有那些列可以显示,所以我根据这个,用ajax模拟出把那些需要显示的列查询出来,用户通过checkbox来模拟操作具体那些列,然后用代码拼好columns(这个过程也可以交给后台完成,前台只传给后台一些指定的值能确定是那些列即可),然后再交给dt去渲染

@akan
akan commented Jul 20, 2016

@occultskyrong 说的靠谱。一般datatable初始化的时候已经把列生成了。再操作比较适合的是隐藏或者显示某些列。所以大概就是2种选择:
1、选一个包含所有情况的列,根据ajax数据决定隐藏或者显示哪些列。
2、每次ajax都根据data重新生成datatable,替换之前的datatable。

@picong
picong commented Jul 20, 2016

我觉得应该可以了,后台动态的数据可以通过循环生成一个个 {"data": "name", "title": columsName["name"]},这种json对象,然后再循环push到columns数组里面,就可以了,@ssy341我认为可行。

@ssy341
Owner
ssy341 commented Jul 20, 2016

@picong 恩,代码写的比较简单粗暴,只是提出一个自己的实现方法,具体的可以在这个基础上自己实现,先简后繁,这样后面做出的东西就不会出太多问题,你要是还有其他更好的,也可以再讨论,我们互相学习

@Smaillife
Collaborator

我的想法是先从后端获取column的配置,写到一个变量上,再实例化datatables,再去请求数据。

@ssy341 ssy341 added the 已解决 label Aug 30, 2016
@ssy341 ssy341 referenced this issue Sep 30, 2016
Closed

动态表头. #26

@ssy341 ssy341 closed this Oct 1, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment