上一篇介绍了DataTable,这一篇在DT的基础之上再使用jquery的一款插件:treegrid,官网地址:http://maxazan.github.io/jquery-treegrid/
一、使用treegrid,需要以下支持
jquery.min.js+jquery.treegrid.min.js
二、后端提供树状列表格式的集合数据,借助前端的DT的配置控制,来在页面上输出满足treegrid格式要求的html
前台:
1 @using Model 2 @{ 3 Layout = null; 4 UserInfo userInfo = null; 5 6 if (ViewData["LoginUser"] != null) 7 { 8 userInfo = ViewData["LoginUser"] as UserInfo; 9 } 10 else 11 { 12 Response.Redirect("/Login/Index"); 13 } 14 } 15 16 <!DOCTYPE html> 17 18 <html> 19 <head> 20 <meta charset="utf-8"> 21 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 22 <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" /> 23 <title>用户列表</title> 24 <link href="~/Content/Scripts/h-ui/css/H-ui.min.css" rel="stylesheet" /> 25 <link href="~/Content/Scripts/h-ui.admin/css/H-ui.admin.css" rel="stylesheet" /> 26 <link href="~/Content/Scripts/Hui-iconfont/1.0.8/iconfont.css" rel="stylesheet" /> 27 <link href="~/Content/Scripts/treegrid/css/jquery.treegrid.css" rel="stylesheet" /> 28 29 <style> 30 .page-container { 31 padding: 10px; 32 } 33 34 .operation { 35 background: #EFEEF0; 36 padding: 3px; 37 } 38 39 .search { 40 background: #EFEEF0; 41 padding: 5px; 42 margin-top: 5px; 43 } 44 45 .table { 46 margin-top: 10px; 47 } 48 49 .dataTables_info { 50 margin-left: 5px; 51 } 52 53 #table1_info { 54 padding: 0; 55 } 56 57 #table1_length { 58 margin-left: 15px; 59 } 60 </style> 61 <!--引入脚本解决兼容性(hack技术,必须放入head中)--> 62 <!--[if lt IE 9]> 63 <script src="~/Content/Scripts/html5_css3/html5shiv.min.js"></script> 64 <script src="~/Content/Scripts/html5_css3/respond.min.js"></script> 65 <script src="~/Content/Scripts/PIE-2.0beta1/PIE_IE678.js"></script> 66 <![endif]--> 67 </head> 68 <body> 69 <div class="page-container"> 70 <div class="operation"> 71 @Html.Partial("CRUDBtn", userInfo) 72 </div> 73 74 <div class="table"> 75 <table id="table1" class="table table-border table-bordered table-bg table-hover"> 76 <thead> 77 <tr class="text-c"> 78 <th><input type="checkbox" name="" value=""></th> 79 <th>菜单名</th> 80 <th>请求路径</th> 81 <th>描述</th> 82 <th>添加时间</th> 83 <th>修改时间</th> 84 </tr> 85 </thead> 86 </table> 87 </div> 88 </div> 89 </body> 90 </html> 91 <script src="~/Content/Scripts/jquery-2.0.3.min.js"></script> 92 <script src="~/Content/Scripts/datatables/1.10.13/jquery.dataTables.min.js"></script> 93 <script src="~/Content/Scripts/layer/2.1/layer.js"></script> 94 <script src="~/Content/Scripts/My97DatePicker/WdatePicker.js"></script> 95 <script src="~/Content/Scripts/h-ui/js/H-ui.js"></script> 96 <script src="~/Content/Scripts/h-ui.admin/js/H-ui.admin.js"></script> 97 <script src="~/Content/Scripts/treegrid/js/jquery.treegrid.min.js"></script> 98 99 <script type="text/javascript"> 100 var table1 = null; 101 $(function () { 102 table1 = initializeTable(); 103 clickDeal(); 104 }); 105 106 /*点击处理*/ 107 function clickDeal() { 108 var addBtn = $("#add"); 109 var deleteBtn = $("#delete"); 110 var editBtn = $("#edit"); 111 var viewBtn = $("#view"); 112 113 $("#search").click(function () { 114 table1.ajax.reload(); 115 return false; 116 }); 117 if (addBtn != null) { 118 addBtn.click(function () { 119 var title = $(this).text().substring(1).trim(); 120 var url = $(this).attr("url"); 121 122 layer_show(title, url, 600, 360); 123 }); 124 } 125 if (deleteBtn != null) { 126 deleteBtn.click(function () { 127 var idArr = []; 128 var url = $(this).attr("url"); 129 130 $("input:checkbox[name=id]:checked").each(function () { 131 var item = this; 132 idArr.push($(item).val()); 133 }); 134 if (idArr.length == 0) { 135 layer.msg("请至少选择一个选项", { icon: 2, time: 2000 }); 136 } 137 else { 138 layer.confirm('确认要删除吗?', function (index) { 139 var loadIndex = layer.load(); 140 $.ajax({ 141 url: url, 142 type: "post", 143 data: { "idArrStr": idArr.toString() }, 144 dataType: "json", 145 success: function (data) { 146 if (data.Pass) { 147 layer.close(loadIndex); 148 layer.msg(data.Msg, { icon: 1, time: 2000 }); 149 table1.ajax.reload(null, false); 150 } else { 151 layer.msg(data.Msg, { icon: 1, time: 2000 }); 152 } 153 }, 154 error: function (msg) { 155 layer.msg(msg.status); 156 } 157 }); 158 }); 159 } 160 }); 161 } 162 if (editBtn != null) { 163 editBtn.click(function () { 164 var idArr = []; 165 var title = $(this).text().substring(1).trim(); 166 var url = $(this).attr("url"); 167 168 $("input:checkbox[name=id]:checked").each(function () { 169 var item = this; 170 idArr.push($(item).val()); 171 }); 172 if (idArr.length != 1) { 173 layer.msg("请选择一个选项", { icon: 2, time: 2000 }); 174 } 175 else { 176 url += "?id=" + idArr[0]; 177 layer_show(title, url, 600, 360); 178 } 179 }); 180 } 181 if (viewBtn != null) { 182 viewBtn.click(function () { 183 var idArr = []; 184 var title = $(this).text().substring(1).trim(); 185 var url = $(this).attr("url"); 186 187 $("input:checkbox[name=id]:checked").each(function () { 188 var item = this; 189 idArr.push($(item).val()); 190 }); 191 if (idArr.length != 1) { 192 layer.msg("请选择一个选项", { icon: 2, time: 2000 }); 193 } 194 else { 195 url += "?id=" + idArr[0]; 196 layer_show(title, url, 600, 360); 197 } 198 }); 199 } 200 201 } 202 203 /*初始化table*/ 204 function initializeTable() { 205 var table = $("#table1").DataTable({ 206 /****************************************表格数据加载****************************************************/ 207 "serverSide": true, 208 "ajax": {//ajax请求数据源 209 "url": "/Power/Manager/Search", 210 "type": "post", 211 "data": function (data) {//添加额外的数据给服务器 212 } 213 }, 214 "columns": [//列绑定 215 { "defaultContent": "" }, 216 { "data": "PowerName" }, 217 { "data": "Url" }, 218 { "data": "Description" }, 219 { "data": "AddTime" }, 220 { "data": "ModifyTime" } 221 ], 222 "columnDefs": [//列定义 223 { 224 "targets": [0], 225 "data": "PowerId", 226 "render": function (data, type, full) {//全部列值可以通过full.列名获取,一般单个列值用data PS:这里的render是有多少列就执行多少次方法。。。不知道为啥 227 return "<input type='checkbox' value='" + data + "' name='id'>"; 228 } 229 }, 230 { 231 "targets": [4], 232 "data": "AddTime", 233 "render": function (data, type, full) {//全部列值可以通过full.列名获取,一般单个列值用data PS:这里的render是有多少列就执行多少次方法。。。不知道为啥 234 if (data == null || data.trim() == "") { return "/"; } 235 else { 236 var dateTime = new Date(parseInt(data.replace("/Date(", "").replace(")/", ""), 10)); 237 var month = dateTime.getMonth() + 1 < 10 ? "0" + (dateTime.getMonth() + 1) : dateTime.getMonth() + 1; 238 var date = dateTime.getDate() < 10 ? "0" + dateTime.getDate() : dateTime.getDate(); 239 return dateTime.getFullYear() + "/" + month + "/" + date; 240 } 241 } 242 }, 243 { 244 "targets": [5], 245 "data": "ModifyTime", 246 "render": function (data, type, full) {//全部列值可以通过full.列名获取,一般单个列值用data PS:这里的render是有多少列就执行多少次方法。。。不知道为啥 247 if (data == null || data.trim() == "") { return "/"; } 248 else { 249 var dateTime = new Date(parseInt(data.replace("/Date(", "").replace(")/", ""), 10)); 250 var month = dateTime.getMonth() + 1 < 10 ? "0" + (dateTime.getMonth() + 1) : dateTime.getMonth() + 1; 251 var date = dateTime.getDate() < 10 ? "0" + dateTime.getDate() : dateTime.getDate(); 252 return dateTime.getFullYear() + "/" + month + "/" + date; 253 } 254 } 255 }, 256 ], 257 "rowCallback": function (row, data, displayIndex) {//行定义 258 if (data.ParentId != "0") { 259 $(row).attr("class", "text-c treegrid-" + data.PowerId + " treegrid-parent-" + data.ParentId); 260 } else { 261 $(row).attr("class", "text-c treegrid-" + data.PowerId); 262 } 263 }, 264 "initComplete": function (settings, json) { //表格初始化完成后调用 265 $("#table1").treegrid({ 266 "initialState": 'collapsed', 267 }); 268 }, 269 /****************************************表格数据加载****************************************************/ 270 /****************************************表格样式控制****************************************************/ 271 "dom": "t<'dataTables_info'il>p",//表格布局 272 "processing": true,//等待加载效果 273 "language": {//语言国际化 274 "lengthMenu": "每页 _MENU_ 条", 275 "zeroRecords": "没有找到记录", 276 "info": "当前显示 _START_ 到 _END_ 条,共 _TOTAL_条", 277 "infoEmpty": "无记录", 278 "paginate": 279 { 280 "first": "首页", 281 "previous": "前一页", 282 "next": "后一页", 283 "last": "末页" 284 }, 285 "processing": "表格在努力渲染中......", 286 "loadingRecords": "加载记录中...",//注意该参数在从服务器加载的时候无效,只有Ajax和客户端处理的时候有效 287 }, 288 "paging": false,//分页功能 289 "ordering": false,//排序功能 290 "autoWidth": false,//自动宽度(这里关闭后,可以随着左侧的隐藏而扩展页面一起100%宽度) 291 /****************************************表格样式控制****************************************************/ 292 }); 293 return table; 294 } 295 296 </script>
后台:
1 public ActionResult Search(DataTable dt) 2 { 3 int total; 4 5 IQueryable<Model.Power> powerIq = CurrentBllSession.PowerBll.GetIQueryable(); 6 total = powerIq.Count(); 7 List<Model.Power> powerList = powerIq.ToList(); 8 powerList = TreeGridList(powerList); 9 dt.recordsTotal = total; 10 dt.recordsFiltered = total; 11 dt.data = powerList; 12 13 return Json(dt); 14 } 15 16 /// <summary> 17 /// 将List转换为TreeGrid格式的List 18 /// </summary> 19 private List<Model.Power> TreeGridList(List<Model.Power> powerList) 20 { 21 List<Model.Power> treegridList=new List<Model.Power>(); 22 23 foreach (var powerOne in powerList.Where(a => a.ParentId == "0" || a.PowerId.Length == 4).OrderBy(a => a.Sort))//一级菜单 24 { 25 treegridList.Add(powerOne); 26 foreach (var powerTwo in powerList.Where(a => a.ParentId != "0" && a.PowerId.Length == 8 && a.ParentId == powerOne.PowerId).OrderBy(a=>a.Sort))//二级菜单 27 { 28 treegridList.Add(powerTwo); 29 foreach (var powerBtn in powerList.Where(a => a.ParentId != "0" && a.PowerId.Length == 8 && a.ParentId == powerTwo.PowerId).OrderBy(a => a.Sort))//按钮 30 { 31 treegridList.Add(powerBtn); 32 } 33 } 34 } 35 36 return treegridList; 37 }
解释说明:
treegrid是通过tr标签上的class内容和tr的位置关系来组织表格中行之间的父子关系和位置关系的,
DT中的配置项:
"rowCallback": function (row, data, displayIndex) {//行定义
if (data.ParentId != "0") {
$(row).attr("class", "text-c treegrid-" + data.PowerId + " treegrid-parent-" + data.ParentId);
} else {
$(row).attr("class", "text-c treegrid-" + data.PowerId);
}
},
就是来控制父子关系的。
而后台的List顺序转换,是为了调整好输出的顺序,从而来控制tr之间的位置关系。
通过DT初始化好表格之后,调用
$("#table1").treegrid({
"initialState": 'collapsed',
});
即可,绘制好树状表格。
效果图: