2017-06-02 17:08:13 sgzhm_casco 阅读数 5747

  在JS中,借助于Bootstrap,我们可以高效地绘制表格。但实际应用中,需要的表格功能更能往往更为复杂,需要在Bootstrap表格类的基础上进行二次开发。

  本文实现的主要是一个三级表格的开发,如下图:

          这里写图片描述

  主要的功能如下:

  1. 点开一级菜单,出现全部二级菜单,并使一级菜单前的“缩回展开”图标由“缩回”变为“展开”;
  2. 点开二级菜单,出现全部三级菜单,并使二级菜单前的“缩回展开”图标由“缩回”变为“展开”;
  3. 在二级菜单处于展开状态下,点击对应的一级菜单项,收回二级菜单,并使一级菜单前的“缩回展开”图标由“展开”变为“缩回”;
  4. 在三级菜单处于展开状态下,点击对应的二级菜单项,收回三级菜单,并使二级菜单前的“缩回展开”图标由“展开”变为“缩回”;
  5. 在三级菜单处于展开状态下,点击对应的一级菜单项,收回二级和三级菜单,并使二级和三级菜单前的“缩回展开”图标由“展开”变为“缩回”;

  其中功能的前4点利用slideToggle()函数+类的添加移除可以实现,这里不再赘述。需要注意的主要是功能的第5点,在相邻级菜单互动的基础上,需要注意一、三级菜单间的互动,实现也较为简单,代码如下:

function StateShow0()
    {
        $(".二级菜单类名").slideToggle("fast");

        if ($("#一级菜单ID").hasClass("glyphicon-plus-sign图标类1")) 
            {
                $("#一级菜单ID").addClass("glyphicon-minus-sign图标类2");
                $("#一级菜单ID").removeClass("glyphicon-plus-sign");
            } 
        else 
            {
                $("#一级菜单ID").addClass("glyphicon-plus-sign");
                $("#一级菜单ID").removeClass("glyphicon-minus-sign");
                $(".二级菜单1类名").css("display","none");
                $(".二级菜单2类型").css("display","none");
                $("#二级菜单1ID").removeClass("glyphicon-minus-sign");
                $("#二级菜单1ID").addClass("glyphicon-plus-sign");
                $("#二级菜单2ID").removeClass("glyphicon-minus-sign");
                $("#二级菜单2ID").addClass("glyphicon-plus-sign");
            }
    }
2019-09-04 15:21:23 weixin_45237517 阅读数 274

实际上,bootstrap或者layui的table都有对应的treegrid插件来实现表格数据的树形展示。但layui的treegrid插件似乎对复杂表头的支持不大好,而在我使用bootstrap的treegrid插件时一直出现样式问题(当然应该是我自己的问题)。于是,我准备自己代码实现一个二级树形表格。所以,此贴给本着学习的态度或者就是不想用插件的同学使用。

实现的效果如下:

在这里插入图片描述
当然,想学习这两个treegrid树形插件的同学,可以去官方文档学习,很ez。
友情链接1:layui treegrid
友情链接2:bootstrap treegrid


不用插件的代码实现思路:利用bootstrap table的隐藏显示行的方法来模拟数据行的树形折叠效果。

一、表头和数据的格式处理:

1、表头中的第一列需要对返回值进行格式化,目的是为了在文字的前面加上向右的箭头来表示数据可以向下展开。
2、且对该添加的箭头绑定点击事件(可以加上鼠标移上去时候的小手样式)
3、而对返回数据的处理中,需加上父子级id的关系(如下面的代码)
:此处的箭头是利用的layui的字体图标,当然也可以用bootstrap的。

let columns = [
    [
        {title: '班组',field: 'team',align: 'center',valign: 'middle', rowspan:2,
            formatter: function (value, row, index) {
                row.index = index;
                if (row.teamStyle == 1){
                    return "<div><i class='layui-icon' οnclick='treeGridClick("+ row.teamId +")' style='cursor:pointer' id='"+ row.teamId +"'>&#xe602;</i>&nbsp;"+ value +"</div>";
                } else {
                    return "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + value;
                }

            }},
        {title: '2019第一季度',field: '',align: 'center',valign: 'middle',colspan:3}
    ],
    [
        {title: '1月',field: '2019-01',align: 'center',valign: 'middle',},
        {title: '2月',field: '2019-02',align: 'center',valign: 'middle',},
        {title: '3月',field: '2019-03',align: 'center',valign: 'middle',},
    ]

]

let data = [
    {'team':'班组1','teamId':'1','teamParentId':'','2019-01':22,'2019-02':33,'2019-03':44},
    {'team':'用户1','teamId':'12','teamParentId':'1','2019-01':1,'2019-02':3,'2019-03':4},
    {'team':'用户2','teamId':'13','teamParentId':'1','2019-01':1,'2019-02':'','2019-03':4},
    {'team':'用户3','teamId':'14','teamParentId':'1','2019-01':20,'2019-02':30,'2019-03':36},
    {'team':'班组2','teamId':'2','teamParentId':'','2019-01':66,'2019-02':77,'2019-03':88},
    {'team':'用户4','teamId':'21','teamParentId':'2','2019-01':11,'2019-02':2,'2019-03':33},
    {'team':'班组3','teamId':'3','teamParentId':'','2019-01':88,'2019-02':55,'2019-03':100},
]

二、表格的初始化渲染和二级数据行的隐藏:

1、因为静态数据渲染不会触发onLoadSuccess方法,所以此处用onPostBody代替(但onPostBody方法在每次调用bootstrap的隐藏显示方法后,均会被调用,暂时没有找到更改好的替代方案)。所以代码中为了避免一直循环赋值,用了parentRowClickFlag是否为空来处理。
2、渲染完成后,会提取出二级数据的index数组(用于渲染完成后的隐藏二级行)。和一级数据行是否展开过的标识数组。

let $table = $("#TableId");
let hideRowIndexs = [];// 需隐藏的行(即二级数据所在行)
let parentRowClickFlag = [];// 父级行是否展开过的标识数组
$table.bootstrapTable({
    data:data,
    columns:columns,
    striped:false,
    sidePagination:'client',
    onPostBody:function (data) {
        if (parentRowClickFlag.length == 0){
            for (let i = 0; i < data.length; i++) {
                if (data[i].teamParentId != ""){
                    hideRowIndexs.push(data[i].index);
                } else {
                    parentRowClickFlag.push({"teamId":data[i].teamId,"isShow":false});
                }
            }
        }
    }
})

// 渲染完成后隐藏子级行
if (hideRowIndexs.length > 0){
    $.each(hideRowIndexs,function (i,index) {
        $table.bootstrapTable('hideRow', {index:index});// 隐藏行
    })
}

三、展开折叠行的箭头点击事件

1、通过控制行的显示隐藏来实现折叠展开,并同时设置箭头的方向。

/**
 * 展开折叠点击方法
 * @param teamId:该行数据的id
 */
treeGridClick = function(teamId){
    // 获取该行是否点击过状态
    let currentRow = {};
    $.each(parentRowClickFlag,function (i,row) {
        if (teamId == row.teamId){
            currentRow = row;
            return false;
        }
    })
    // 控制行的显示隐藏来模拟展开折叠
    if (!currentRow['isShow']){// 开
        $.each(data,function (i,da) {
            if (teamId == da.teamParentId){
                $table.bootstrapTable('showRow', {index:da.index});
            }
        })
        currentRow['isShow'] = true;
    } else {// 合
        $.each(data,function (i,da) {
            if (teamId == da.teamParentId){
                $table.bootstrapTable('hideRow', {index:da.index});
            }
        })
        currentRow['isShow'] = false;
    }
    // 统一改变展开折叠的箭头样式
    $.each(parentRowClickFlag,function (i,row) {
        if (row.isClick){
            $("#" + row.teamId).html("&#xe61a;");
        } else {
            $("#" + row.teamId).html("&#xe602;");
        }
    })
}
2019-12-16 20:33:02 weixin_43790879 阅读数 10

业务需求

项目中需要实现二级页面的展示,父级下面有多个子级列表

实现结果图:
在这里插入图片描述
实现步骤:

1:可以去jqGrid中文官网去找实例
网址:https://blog.mn886.net/jqGrid/
2:以下代码是我的实现过程

<script>
            $("#tb").jqGrid(
                {
                url : '${pageContext.request.contextPath}/album/findAlbum',
                datatype : "json",
                height : 290,
                colNames : [ 'ID','标题', '内容', '作者', '封面', '上架时间' ],
                colModel : [
                {name : 'id', width : 55,},
                {name : 'title',width : 90,editable:true,},
                {name : 'content',width : 100,editable:true,},
                {name : 'author',width : 80,editable:true,},
                {name : 'src',width : 80,editable:true,formatter:showPicture,edittype:'file',
                    editoptions:{enctype:"multipart/form-data"}},
                {name : 'addTime',width : 80,},
                ],
                    editurl:'${pageContext.request.contextPath}/album/edit',
                    autowidth:true,//数据表格是否自适应父容器的大小宽度
                    styleUI:"Bootstrap",
                rowNum : 3,//每页展示的页数
                rowList : [ 3, 6, 9, 12 ],
                pager : '#pg',//开启底部工具栏
                viewrecords : true,//分页展示总条数
                multiselect : true,//复选框是否展示
                subGrid : true,//开启二级表格
                caption : "章节列表",
                subGridRowExpanded : function(subgrid_id, row_id) {
                    var subgrid_table_id = subgrid_id + "_t";
                    var pager_id = "p_" + subgrid_table_id;
                    $("#" + subgrid_id).html(
                        "<table id='" + subgrid_table_id
                        + "' class='scroll'></table><div id='"
                        + pager_id + "' class='scroll'></div>");
                    $("#" + subgrid_table_id).jqGrid(
                        {
                            url : '${pageContext.request.contextPath}/chapter/findChapter?albumId='+row_id,
                            datatype : "json",
                            colNames : [ 'ID', '标题', '上架时间', '大小','播放' ],
                            colModel : [
                                {name : "id",},
                                {name : "title",editable:true,width :60},
                                {name : "addTime",},
                                {name : "size",width :50,},
                                {name : "src",editable:true,formatter:showAudio,edittype:'file',
                                    editoptions:{enctype:"multipart/form-data"}

                                }
                            ],
                            editurl:'${pageContext.request.contextPath}/chapter/edit?albumId='+row_id,
                            autowidth:true,//数据表格是否自适应父容器的大小宽度
                            multiselect : true,
                            styleUI:"Bootstrap",
                            rowNum : 3,
                            rowList : [ 3, 6, 9, 12 ],
                            pager : pager_id,
                            viewrecords : true,
                            height : 160,
                            //height : '100%'
                        });
                    $("#" + subgrid_table_id).jqGrid('navGrid',
                        "#" + pager_id, {
                            edit : true,
                            add : true,
                            del : true
                        },{
                        //修改的操作
                            closeAfterEdit:true,

                            afterSubmit:function (result) {

                                if (result.responseJSON.data=="error"){
                                    return "111";
                                };
                                console.log(result),
                                    $.ajaxFileUpload({
                                        url:'${pageContext.request.contextPath}/chapter/upload',
                                        fileElementId:'src',
                                        data:{id:result.responseJSON.data},
                                        type:'post',
                                        datatype:'json',
                                        success:function () {
                                            $("#tb").trigger("reloadGrid")
                                        }
                                    });
                                return "123";
                            }

                        },{
                        //添加的操作
                            closeAfterAdd:true,

                            afterSubmit:function (result) {
                                console.log(result),
                                    $.ajaxFileUpload({
                                        url:'${pageContext.request.contextPath}/chapter/upload',
                                        fileElementId:'src',
                                        data:{id:result.responseJSON.data},
                                        type:'post',
                                        datatype:'json',
                                        success:function () {
                                            $("#tb").trigger("reloadGrid")
                                        }
                                    });
                                return "123";
                            }


                        },{
                        //删除的操作
                            closeAfterDel:true,
                        }

                        );
                },
                    subGridRowColapsed : function(subgrid_id, row_id) {
                        // this function is called before removing the data
                        //var subgrid_table_id;
                        //subgrid_table_id = subgrid_id+"_t";
                        //jQuery("#"+subgrid_table_id).remove();
                    }
                });
                $("#tb").jqGrid('navGrid', '#pg', {
                    edit : true,
                    add : true,
                    del : true
            },{
                    //控制修改操作
                    closeAfterEdit:true,

                    afterSubmit:function (result) {
                        if (result.responseJSON.data=="error"){
                            return "111";
                        };
                        console.log(result),
                            $.ajaxFileUpload({
                                url:'${pageContext.request.contextPath}/album/upload',
                                fileElementId:'src',
                                data:{id:result.responseJSON.data},
                                type:'post',
                                datatype:'json',
                                success:function () {
                                    $("#tb").trigger("reloadGrid")
                                }
                            });
                        return "123";
                    }

                },{


                    //控制添加操作
                    closeAfterAdd:true,
                    afterSubmit:function (result) {
                        console.log(result),
                            $.ajaxFileUpload({
                                url:'${pageContext.request.contextPath}/album/upload',
                                fileElementId:'src',
                                data:{id:result.responseJSON.data},
                                type:'post',
                                datatype:'json',
                                success:function () {
                                    $("#tb").trigger("reloadGrid")
                                }
                            });
                        return "123";
                    }

                },{
                    //控制删除操作
                    closeAfterDel:true,

                }


            );

            function showPicture(cellvalue){
                return "<img src='${pageContext.request.contextPath}/img/"+cellvalue+"' height='50' width='70'/>";
            }
            function showAudio(cellvalue){
                return "<audio controls style='height: 20px;width:200px'>\n" +
                "  <source src='${pageContext.request.contextPath}/mp3/"+ cellvalue +"'  type=\"audio/mpeg\">\n" +
                "</audio>";
            }

    </script>

以上是实现过程
这是一级表格追加的div 详细教程可以参考官网

2019-11-20 16:39:43 qq_38183592 阅读数 16

效果展示

在这里插入图片描述
这种常见的前端需求,如何实现上面的效果呢?

主要代码

  1. html 部分,前端用的是django模板引擎,但是不管什么框架都一样的
    我们给表格的每一行的后面增加一行 设置style格式display:none默认不展示。用js去修改他达到动态展示效果
		<tr class="detail-view" style="display: none">
                 <td colspan="6" id="{{ group.id }}">
                     <ol class="panel-default"></ol>
                 </td>
         </tr>
<table class="table">
              <thead>
            <tr>
                <th  style="text-align: center">集群名字</th>
                <th  style="text-align: center">集群类型</th>
                <th  style="text-align: center">sure应用名</th>
                <th  style="text-align: center">切换方式</th>
                <th  style="text-align: center">备份策略</th>
                <th  style="text-align: center">备注信息</th>
                <th  style="text-align: center"></th>
            </tr>
              </thead>
             <tbody id="dataBody">
                     {% for group in serverGroups %}
                <tr id="{{ group.id }}">
                  <td  style="text-align: center"><a rel="#">{{ group.group_name }}</a></td>
                  <td  style="text-align: center">{% ifequal group.group_type '0' %}公共{% endifequal %}{% ifequal group.group_type '1'%}私有{% endifequal %}{% ifequal group.group_type '2'%}其它{% endifequal %}</td>
                  <td  style="text-align: center">{{ group.sure_name }}</td>
                  <td  style="text-align: center">{{ group.switch_style  }}</td>
                  <td  style="text-align: center">{{ group.backup_style }}</td>
                  <td  style="text-align: center">{{ group.remark }}</td>
                  <td  style="text-align: center"><a href="#" class="sftpNode" ><i class="glyphicon glyphicon-plus icon-plus"></i></a></td>
               </tr>
                 <tr class="detail-view" style="display: none">
                 <td colspan="6" id="{{ group.id }}">
                     <ol class="panel-default"></ol>
                 </td>
                 </tr>
            {% endfor %}
             </tbody>
            </table>
  1. js代码 调用jquery,绑定每一个 “tr” 标签,因为每一个tr都有一个 “加号” 当鼠标点击加号 触发js事件,然后去判断子列表现在的状态并作出更改。顺便附上ajax代码。列表展示应该是异步去获取数据的,我们最好不要在页面加载的同时将所有数据填充到子列表,会应用效率
 $("#dataBody").find("tr").each(function(){
        var that = this;
        var groupId = $(that).attr("id");
        $(this).find("> td > .sftpNode").on("click", function(){
            if($(that).next().is(":hidden")){
                $(this).find(".glyphicon").toggleClass("glyphicon-minus icon-minus");
                $(that).next().show();
                    $.ajax({
                    url: "/server/list",
                    data: {'id':parseInt(groupId),csrfmiddlewaretoken:'{{ csrf_token }}'},
                    type: 'GET',
                    dataType: "json",
                    success:function (data) {
                        serverList = data["serverList"]
                        $('#dataBody').find(".detail-view").find("#"+groupId).find("ol").find("li").remove()
                        for (j in serverList){
                            var p = "<li><p>&emsp;&emsp;&emsp;"+serverList[j]["relation"]+"&nbsp;&nbsp;&nbsp;&nbsp;ip: "+serverList[j]["ip"]+"&nbsp;&nbsp;&nbsp;&nbsp vip: "+serverList[j]["vip"]+"&nbsp;&nbsp;&nbsp;&nbsp owner: "
                                +serverList[j]["owner"]+"&nbsp;&nbsp;&nbsp;&nbsp; status: "+serverList[j]["status"]+"&nbsp;&nbsp;&nbsp;&nbsp sftpUserCount: "+serverList[j]["sftpUserCount"]+"</p></li>";
                            $('#dataBody').find(".detail-view").find("#"+groupId).find("ol").append(p)
                        }
                    },
                    error:function(error){
                        console.log(error)
                    }
                })
            } else {
                $(this).find(".glyphicon").toggleClass("glyphicon-minus icon-minus");
                $(that).next().hide();
            }
        });
         });

效果展示

2017-03-15 08:32:37 kangguowei 阅读数 29209

官网:http://maxazan.github.io/jquery-treegrid/


引入文件:

<link rel="stylesheet" href="statics/treeGrid/jquery.treegrid.css">


<script type="text/javascript" src="statics/treeGrid/jquery.treegrid.js"></script>
        <script type="text/javascript" src="statics/treeGrid/jquery.treegrid.bootstrap3.js"></script>

用法:
其静态页面:

 <table class="table tree-2 table-bordered table-striped table-condensed">
                <tr class="treegrid-1">
                    <td>Root node 1</td><td>Additional info</td>
                </tr>
                <tr class="treegrid-2 treegrid-parent-1">
                    <td>Node 1-1</td><td>Additional info</td>
                </tr>
                <tr class="treegrid-3 treegrid-parent-1">
                    <td>Node 1-2</td><td>Additional info</td>
                </tr>
                <tr class="treegrid-4 treegrid-parent-3">
                    <td>Node 1-2-1</td><td>Additional info</td>
                </tr>
                <tr class="treegrid-5">
                    <td>Root node 2</td><td>Additional info</td>
                </tr>
                <tr class="treegrid-6 treegrid-parent-5">
                    <td>Node 2-1</td><td>Additional info</td>
                </tr>
                <tr class="treegrid-7 treegrid-parent-5">
                    <td>Node 2-2</td><td>Additional info</td>
                </tr>
                <tr class="treegrid-8 treegrid-parent-7">
                    <td>Node 2-2-1</td><td>Additional info</td>
                </tr>        
            </table>    

 $(document).ready(function() {
                $('.tree').treegrid();
                $('.tree-2').treegrid({
                    expanderExpandedClass: 'glyphicon glyphicon-minus',
                    expanderCollapsedClass: 'glyphicon glyphicon-plus'
                });

            });

根据其静态页面我们可以看到,只需class按照其样式拼接就可以达到效果,所以可以去后台取数据,反给前台,后台的数据包含的信息要有
pid id level(节点等级) 等关键信息,当然这个不是必须,可以自行处理,只需知道想达到效果就要按照样式拼接.


效果展示(代码不全,仅供参考):

 <table class="table tree-2 table-bordered table-striped table-condensed">
                                  <thead>
                                    <th>模版名称</th>
                                    <th>检查评定</th>
                                    <th>备注</th>
                                  </thead>
                                  <tbody id="treeGrid">

                                  </tbody>
                              </table>
   js:                           
    //查询定制模板项
           $("#makeProject").change(function () {
               var mid = $(this).val();
               $.get("mvc/safeCheck/get-make-Project/"+mid+"?"+Math.random(), function (resp) {
                   var zNodes = resp.data;
                   //清空
                   $("#treeGrid").html("");
                   $.each(zNodes, function (index,item) {
                       if(item.level == 1) {//一级
                           $("#treeGrid").append("" +
                                   " <tr class='treegrid-"+item.id+"'>"
                                        +"<td>"+item.name+"</td><td> </td><td>"+" "+"</td>"
                           +"</tr>");
                       } else if (item.level == 2) {//二级
                           $("#treeGrid").append("" +
                                   " <tr class='treegrid-"+item.id+" treegrid-parent-"+item.pId+"'>"
                                   +"<td>"+item.name+"</td><td> </td><td>"+" "+"</td>"
                                   +"</tr>");
                       } else if (item.level == 3) {//三级
                           $("#treeGrid").append("" +
                                   " <tr class='treegrid-"+item.id+" treegrid-parent-"+item.pId+"'>"
                                   +"<td>"+item.name+"</td><td> </td><td>"+" "+"</td>"
                                   +"</tr>");
                       } else{//四级
                           if (item.value){//分值类型
                               $("#treeGrid").append("" +
                                       " <tr id='"+item.id+"' class='treegrid-"+item.id+" treegrid-parent-"+item.pId+"'>"
                                       +"<td>"+item.name+"</td><td style='width: 20%'>"+"分值:&nbsp;<input  style='width: 40%' value='10' type= 'number' >&nbsp;&nbsp;满分:"+item.value+"</td><td>"+"<input type='text'>"+"</td>"
                                       +"</tr>");
                           }else {//是否合格项
                               $("#treeGrid").append("" +
                                       " <tr id='"+item.id+"' class='treegrid-"+item.id+" treegrid-parent-"+item.pId+"'>"
                                       +"<td>"+item.name+"</td><td style='width: 10%'>"+"<input type= 'checkbox' value='Y' onclick='setVal($(this));' >不合格"+"</td><td>"+"<input type='text'>"+"</td>"
                                       +"</tr>");
                           }
                       }
                   });
                   $('.tree-2').treegrid({
                       expanderExpandedClass: 'glyphicon glyphicon-minus',
                       expanderCollapsedClass: 'glyphicon glyphicon-plus'
                   });

               }, "json");

           });
后台实体类字段举例:
    private String id;
    private String name;
    private String pid;
    private String levelType;//等级

这里写图片描述

没有更多推荐了,返回首页