treegrid级联勾选或深度级联勾选扩展
- 格式:doc
- 大小:46.50 KB
- 文档页数:7
JQuery EasyUI之treegrid级联勾选的简单改进版最近需要搞点权限方面的东西,后台用的是Jquery Easyui treegrid 1.2.6,可惜没有级联勾选功能Tree如下格式----1--------2--------3----4--------5--------6--------7根节点是0,级别是0,有两个子节点1,4,级别为1,子节点1,4各自有多节点分别是2,3和5,6,7,级别为2需求如下1.选择根节点0的时候,必须选择所有后代节点,1-7全部都要被选择2.取消选择根节点0的时候,必须取消选择所有后代节点,1-7全部都要被取消选择3.当选择节点1的时候,必须将1的父节点0也选择,但此时0的其它子节点就不能自动被选择了,保持原样4.取消1节点的时候,同2步,后代节点2,3都取消5.当选择2节点的时候,需要选择1,0两个节点,6.取消2的时候,需要看3是否有没有被选择,如果有则1选择,如果3没选,则1不选,0是否被选需要看1或者4有没有被选择总结一下1.选择某节点的时候,必须选择这个节点下面的所有后代节点,反之,取消选择后代子节点2.选择某节点的时候,必须将此节点的父节点选上,包含所有前代父节点取消某节点的时候,如果此节点的兄弟节点都没有被选择,那么父节点,也取消选择,换句话说就是需要看父节点下面的子节点有没有被选择的,有那么父节点仍然选择,如果没有一个被选择,那么父节点也取消选择-------------找前人的劳动成功搜索到一篇文章,感谢原作者里面有两种方式实现了上述需求的的1,实现2中的一部分,不过在取消节点时候,父节点是否取消有点问题我主要是用第二种方式(属性方式,非函数方式),这里我加上了一个函数判断父节点是否需要被取消1 /**2 * 级联判断父节点的子节点是否有被选择的3 * @param {Object} target4 * @param {Object} id 节点ID5 * @return {TypeName}6 */7 function IsParentHasSelectedChildren(target,id,idField,status)8 {9 var count=0;10 var children = target.treegrid('getChildren',id);11 var selectNodes = $(target).treegrid('getSelections');//获取当前选中项12 var p=target.treegrid('find',id);13 //注意,这里的children是指后代所有子节点,不是指儿子节点,所以要加上children[i]['_parentId']==p[idField]过滤出儿子节点14 for(var i=0;i<children.length ;i++ )15 {16 var childId = children[i][idField];17 for(var j=0;j<selectNodes.length;j++){18 if(selectNodes[j][idField]==childId &&children[i]['_parentId']==p[idField])19 count++;20 }21 }22 //注意,click 函数在unselect事件之前运行,这里需要减去自己23 return count-1>0;24 }。
一、什么是treegridview?treegridview 是一种常用的控件,它是基于 gridview 和 treeview 的组合,可以实现树形结构和表格数据的显示,可以展示出树形结构并具有表格的数据功能。
treegridview 是一种常用的控件,用法灵活,功能强大,可以满足各种复杂的数据展示需求。
二、treegridview 的基本用法1. 控件的引用首先需要引用 treegridview 控件,在项目中添加对 treegridview 的引用,引用方式一般是通过将相关的 DLL 文件添加到项目中,然后在项目的代码文件中添加对 treegridview 控件命名空间的引用。
2. 控件的初始化treegridview 控件的初始化工作一般包括设置控件的基本属性、绑定数据源和设置事件处理程序等。
需要注意的是,treegridview 控件的初始化工作一般是在页面加载事件中完成的,以确保在页面首次加载时能够正确显示数据。
3. 数据绑定treegridview 控件的数据绑定工作一般是通过设置控件的数据源来实现的。
在数据绑定过程中,需要注意确保数据源的结构能够正确地映射到树形结构和表格数据的显示需求。
4. 自定义样式treegridview 控件的样式可以通过设置控件的样式属性来实现。
控件的样式设置一般包括设置表头样式、行样式和单元格样式等。
通过自定义样式,可以使 treegridview 控件在页面中展示出符合项目需求的外观效果。
5. 事件处理treegridview 控件的事件处理工作一般包括设置控件的事件处理程序,并在事件处理程序中编写相应的逻辑代码。
在事件处理过程中,需要注意确保事件处理程序能够正确地响应用户操作,并能够对控件的数据进行相应的处理。
6. 控件的功能扩展treegridview 控件的功能还可以通过扩展控件的自定义列、自定义模板和自定义编辑等功能来实现。
通过扩展控件的功能,可以为项目定制出更符合实际需求的数据展示和操作界面。
介绍扩展TreeView控件:联动复选框(复选框的全选和取消全选)。
选中指定的父复选框,则设置其所有子复选框为选中状态;取消选中指定的父复选框,则设置其所有子复选框为取消选中状态。
如果某父复选框的所有子复选框为均选中状态,则设置该父复选框为选中状态;如果某复选框的所有子复选框至少有一个为取消选中状态,则设置该父复选框为取消选中状态使用方法(设置属性):AllowCascadeCheckbox - 是否启用联动复选框功能关键代码相关的js//----------------------------// ///----------------------------/*Helper 开始*/String.prototype.yy_stv_startsWith =function(s){/// <summary>StartsWith()</summary>var reg =new RegExp("^" + s);return reg.test(this);}function yy_stv_addEvent(obj, evtType, fn){/// <summary>绑定事件</summary>// FFif (obj.addEventListener){obj.addEventListener(evtType, fn, true);return true;}// IEelse if (obj.attachEvent){var r = obj.attachEvent("on" + evtType, fn);return r;}else{return false;}}/*Helper 结束*//*联动复选框开始*/var yy_stv_ccTreeView_pre =new Array(); // cs中动态向其灌数据(TreeView内控件ID的前缀数组)function yy_stv_ccClickCheckbox(e){/// <summary>单击复选框时</summary>var evt = e || window.event; // FF || IEvar obj = evt.target || evt.srcElem ent // FF || IEyy_stv_foreachChildCheckbox(obj);yy_stv_foreachParentCheckbox(obj);}function yy_stv_checkParentCheckbox(table, checked){/// <summary>设置父复选框的状态</summary>var nodes = table.parentNode.parent Node.childNodes;for (var i=1; i<nodes.length; i++){if (nodes[i] == table.parentNode){if (typeof(nodes[i-1]) == 'undefined' || typeof(nodes[i-1].rows) == 'un defined') return;for (var x=0; x < nodes[i-1].rows.length; x++){for (var j=0; j < nodes[i-1].rows[x].cells.length; j++){// debugger;var chk = nodes[i-1].rows[x].cells[j].childNodes[0];if (typeof(chk) != 'undefined' && chk.tagName == "INPUT" && ch k.type == "checkbox"){chk.checked = checked;yy_stv_foreachParentCheckbox(nodes[i-1]);return;}}}}}}function yy_stv_foreachChildCheckbox(obj){/// <summary>单击父复选框时,设置其子复选框的选中状态</summary>var checked;if (obj.tagNam e == "INPUT" && obj.type == "checkbox"){checked = obj.checked;do{obj = obj.parentNode;}while (obj.tagName != "TABLE")}var nodes = obj.parent Node.childNodes;for (var i=0; i<nodes.length - 1; i++){if (nodes[i] == obj && nodes[i + 1].tagName == "DIV"){var elem ents = nodes[i+1].getElementsByTagName("INPUT");for (j=0; j< elements.length; j++){if (elem ents[j].type == 'checkbox'){elem ents[j].checked = checked;}}}}}function yy_stv_foreachParentCheckbox(obj){/// <summary>单击某一复选框时,设置其父复选框的选中状态</summary>var checkedNum = 0;var uncheckedNum = 0;if (obj.tagNam e == "INPUT" && obj.type == "checkbox"){do{obj = obj.parentNode;}while (obj.tagName != "TABLE")}var tables = obj.parentNode.getElementsByTagName("TABLE");if (typeof(tables) == 'undefined') return;for (var i=0; i < tables.length; i++){for (var x=0; x < tables[i].rows.length; x++){for (var j=0; j < tables[i].rows[x].cells.length; j++){var chk = tables[i].rows[x].cells[j].childNodes[0];if (typeof(chk) != 'undefined' && chk.tagName == "INPUT" && chk.t ype == "checkbox"){if (chk.checked)checkedNum ++;elseuncheckedNum ++;}}}}if (uncheckedNum == 0){yy_stv_checkParentCheckbox(obj, true);}else{yy_stv_checkParentCheckbox(obj, false);}}function yy_stv_attachCheckboxClickListener(){/// <summary>监听所有联动复选框的单击事件</summary>var elem ents = docum ent.getElementsByTagName("INPUT");for (i=0; i< elements.length; i++){if (elem ents[i].type == 'checkbox'){for (j=0; j<yy_stv_ccTreeView_pre.length; j++){if (elem ents[i].id.yy_stv_startsWith(yy_stv_ccTreeView_pre[j])){yy_stv_addEvent(elements[i], 'click', yy_stv_ccClickCheckbox);break;}}}}}if (docum ent.all){window.attachEvent('onload', yy_stv_attachCheckboxClickListener);}else{window.addEventListener('load', yy_stv_attachCheckboxClickListener, false); }/*联动复选框结束*/说明:1、页面加载时为指定的TreeView的所有复选框绑定单击事件(根据复选框的前缀判断其是否属于指定的复选框)2、单击某复选框,则遍历其所有子复选框,并进行相应的操作。
treegrid树形表格的完美运⽤⼀问题描述:树形表格TreeGrid在⽇常项⽬中还是运⽤的⽐较多的,哪我们在项⽬中,应该怎么引⼊和使⽤TreeGrid呢?⼆使⽤步骤1.⾸先我们需要在项⽬中,引⼊TreeGrid组件需要引⼊的⽂件<!-- 引⼊treegrid--><link rel="stylesheet" th:href="@{/static/js/plugins/bootstrap-table-treegrid/jquery.treegrid.min.css}"><script type="text/javascript" th:src="@{/static/js/plugins/bootstrap-table-treegrid/bootstrap-table-treegrid.js}"></script><script type="text/javascript" th:src="@{/static/js/plugins/bootstrap-table-treegrid/jquery.treegrid.min.js}"></script> 2. 需要在页⾯定义⼀个容器<div><div><h1></h1><table id="menuTable"></table><br/></div></div> 3. JS代码加载数据1var menus = [[${menus}]]; //后台传递的过来的数据2var $table = $('#menuTable');3// '[{"id":1,"pid":0,"name":"⽤户管理",url:'',icon:'',"permission":{}},' +4 $(function() {5//加载树形表格6 $table.bootstrapTable({7 data:menus,8 idField: 'id',9 dataType:'jsonp',10 columns: [11 { field: 'check', checkbox: true, formatter: function (value, row, index) {12if (row.check == true) {13// console.log(row.serverName);14//设置选中15return { checked: true };16 }17 }18 },19 { field: 'name', title: '名称' },20 { field: 'url', title: '路径' },21 { field: 'icon', title: '图标' },22// {field: 'id', title: '编号', sortable: true, align: 'center'},23 {field: 'pid', title: '所属上级',formatter:'pidFormatter'},24 { field: 'permission', title: '权限值', sortable: true, align: 'center', formatter: 'permissionFormatter' },25 { field: 'operate', title: '操作', align: 'center', events : operateEvents, formatter: 'operateFormatter' },26 ],30//在哪⼀列展开树形31 treeShowField: 'name',32//指定⽗id列33 parentIdField: 'pid',35 onResetView: function(data) {36//console.log('load');37 $table.treegrid({38 initialState: 'collapsed',// 所有节点都折叠39// initialState: 'expanded',// 所有节点都展开,默认展开40 treeColumn: 1,41 expanderExpandedClass: 'mdi mdi-minus', //图标样式42 expanderCollapsedClass: 'mdi mdi-plus',43 onChange: function() {44 $table.bootstrapTable('resetWidth');45 }46 });48//只展开树形的第⼀级节点49 $table.treegrid('getRootNodes').treegrid('expand');51 },52 onCheck:function(row){53var datas = $table.bootstrapTable('getData');54// 勾选⼦类55 selectChilds(datas,row,"id","pid",true);5657// 勾选⽗类58 selectParentChecked(datas,row,"id","pid")5960// 刷新数据61 $table.bootstrapTable('load', datas);62 },6364 onUncheck:function(row){65var datas = $table.bootstrapTable('getData');66 selectChilds(datas,row,"id","pid",false);67 $table.bootstrapTable('load', datas);68 }70 });4 最终效果5 最后实践赶快⾏动起来测试⼀下吧,需要源码的,可以联系我。
jQueryEasyUIAPI中⽂⽂档-TreeGrid树表格使⽤介绍扩展⾃ $.fn.datagrid.defaults,⽤ $.fn.treegrid.defaults 重写了 defaults。
依赖datagrid⽤法复制代码代码如下:<table id="tt"></table>复制代码代码如下:$('#tt').treegrid({url:'treegrid_data.json',treeField:'name',columns:[[{title:'Task Name',field:'name',width:180},{field:'persons',title:'Persons',width:60,align:'right'},{field:'begin',title:'Begin Date',width:80},{field:'end',title:'End Date',width:80}]]});特性其特性扩展⾃ datagrid,下列是为 treegrid 增加的特性。
treeField string定义树节点的字段。
nullanimate boolean定义当节点展开或折叠时是否显⽰动画效果。
false其事件扩展⾃ datagrid,下列是为 treegrid 增加的事件。
onClickRow row当⽤户点击⼀个节点时触发。
onDblClickRow row当⽤户双击⼀个节点时触发。
onBeforeLoad row, param发出⼀个加载数据的请求前触发,返回 false 就取消加载动作。
onLoadSuccess row, data当数据加载成功时触发。
一、概述element 树形表格级联选择是指在一个树形表格中进行选择时,选择一个节点时会影响其他节点的选择状态,实现节点间的级联关系。
二、什么是 element 树形表格级联选择element 树形表格级联选择是基于 element UI 框架的一种前端交互方案,通过这种方案可以方便地实现树形表格中节点间的级联选择功能。
三、element 树形表格级联选择的特点1. 多级树形结构:element 树形表格级联选择支持多级树形结构,用户可以根据实际业务需求构建多层级的树形数据。
2. 自定义选择模式:element 树形表格级联选择支持多种选择模式,用户可以根据需求选择单选、多选、级联选择等不同的选择方式。
3. 灵活配置:element 树形表格级联选择提供丰富的配置选项,用户可以根据实际需求对选择逻辑进行灵活配置,满足不同业务场景的需求。
四、element 树形表格级联选择的应用场景1. 组织架构选择:在企业管理系统中,通常需要对组织架构进行选择,例如选择某个部门时,需要同步选择该部门下的所有子部门。
2. 商品分类选择:在电商系统中,通常需要对商品进行分类选择,例如选择某个分类时,需要同步选择该分类下的所有子分类。
3. 权限分配:在后台管理系统中,通常需要对用户权限进行分配,例如选择某个权限时,需要同步选择该权限下的所有子权限。
五、如何实现 element 树形表格级联选择1. 构建树形数据:首先需要准备好树形结构的数据,可以是从后端接口获取的数据,也可以是手动构建的静态数据。
2. 配置选项:根据实际需求对 element 树形表格级联选择的选项进行配置,包括选择模式、级联选择规则等。
3. 绑定事件:通过监听选择事件,实现节点间的级联选择逻辑,确保用户在选择一个节点时能够影响其他节点的选择状态。
4. 页面展示:将 element 树形表格级联选择组件添加到页面中,展示给用户进行选择操作。
六、element 树形表格级联选择的实现案例```html<template><div><el-tree:data="treeData"show-checkbox:props="defaultProps"check="handleCheckChange"></el-tree></div></template>``````javascript<script>export default {data() {return {treeData: [{label: '一级 1',children: [{label: '二级 1-1',children: [{ label: '三级 1-1-1' }, { label: '三级 1-1-2' } ]},{label: '二级 1-2',children: [{ label: '三级 1-2-1' },{ label: '三级 1-2-2' }]}]}],defaultProps: {children: 'children',label: 'label'}};},methods: {handleCheckChange(data, checked) {// 在这里处理节点选择事件,实现级联选择逻辑 }}};</script>```七、element 树形表格级联选择的使用注意事项1. 数据同步:在使用 element 树形表格级联选择时,需要确保选择状态能够及时同步至后端数据,以保证数据的一致性。
bootstrap-treeview树形菜单带复选框以及级联选择<div id="searchTree"></div><script>var treeData = [{text: "Parent 1",nodes: [{text: "Child 1",nodes: [{text: "Grandchild 1"}, {text: "Grandchild 2",nodes: [{text: "Grandchild 2-1",nodes: [{text: "Grandchild 2-1-1"}, {text: "Grandchild 2-2-1",}]}, {text: "Grandchild 1-2",}]}]}, {text: "Child 2",nodes: [{text: "Grandchild 2-1"}, {text: "Grandchild 2-2",}]}]}, {text: "Parent 2",id:'11111'}, {text: "Parent 3"}, {text: "Parent 4"}, {text: "Parent 5"}];var nodeCheckedSilent = false;function nodeChecked(event, node) {if (nodeCheckedSilent) {return;}nodeCheckedSilent = true;checkAllParent(node);checkAllSon(node);nodeCheckedSilent = false;}var nodeUncheckedSilent = false;function nodeUnchecked(event, node) {if (nodeUncheckedSilent)return;nodeUncheckedSilent = true;uncheckAllParent(node);uncheckAllSon(node);nodeUncheckedSilent = false;}//选中全部⽗节点function checkAllParent(node) {$('#searchTree').treeview('checkNode', node.nodeId, {silent: true});var parentNode = $('#searchTree').treeview('getParent', node.nodeId);if (!("nodeId" in parentNode)) {return;} else {checkAllParent(parentNode);}}//取消全部⽗节点function uncheckAllParent(node) {$('#searchTree').treeview('uncheckNode', node.nodeId, {silent: true});var siblings = $('#searchTree').treeview('getSiblings', node.nodeId);var parentNode = $('#searchTree').treeview('getParent', node.nodeId);if (!("nodeId" in parentNode)) {return;}var isAllUnchecked = true; //是否全部没选中for (var i in siblings) {if (siblings[i].state.checked) {isAllUnchecked = false;break;}}if (isAllUnchecked) {uncheckAllParent(parentNode);}}//级联选中所有⼦节点function checkAllSon(node) {$('#searchTree').treeview('checkNode', node.nodeId, {silent: true});if (node.nodes != null && node.nodes.length > 0) {for (var i in node.nodes) {checkAllSon(node.nodes[i]);}}}//级联取消所有⼦节点function uncheckAllSon(node) {$('#searchTree').treeview('uncheckNode', node.nodeId, {silent: true});if (node.nodes != null && node.nodes.length > 0) {for (var i in node.nodes) {uncheckAllSon(node.nodes[i]);}}}$('#searchTree').treeview({showCheckbox: true,data: treeData,onNodeChecked: nodeChecked,onNodeUnchecked: nodeUnchecked});</script>。
jquery插件treegrid树状表格的使⽤⽅法详解(.Net平台)⼀、使⽤treegrid,需要以下⽀持jquery.min.js+jquery.treegrid.min.js⼆、后端提供树状列表格式的集合数据,借助前端的DT的配置控制,来在页⾯上输出满⾜treegrid格式要求的html前台:@using Model@{Layout = null;UserInfo userInfo = null;if (ViewData["LoginUser"] != null){userInfo = ViewData["LoginUser"] as UserInfo;}else{Response.Redirect("/Login/Index");}}<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" /><title>⽤户列表</title><link href="~/Content/Scripts/h-ui/css/H-ui.min.css" rel="stylesheet" /><link href="~/Content/Scripts/h-ui.admin/css/H-ui.admin.css" rel="stylesheet" /><link href="~/Content/Scripts/Hui-iconfont/1.0.8/iconfont.css" rel="stylesheet" /><link href="~/Content/Scripts/treegrid/css/jquery.treegrid.css" rel="stylesheet" /><style>.page-container {padding: 10px;}.operation {background: #EFEEF0;padding: 3px;}.search {background: #EFEEF0;padding: 5px;margin-top: 5px;}.table {margin-top: 10px;}.dataTables_info {margin-left: 5px;}#table1_info {padding: 0;}#table1_length {margin-left: 15px;}</style><!--引⼊脚本解决兼容性(hack技术,必须放⼊head中)--><!--[if lt IE 9]><script src="~/Content/Scripts/html5_css3/html5shiv.min.js"></script><script src="~/Content/Scripts/html5_css3/respond.min.js"></script><script src="~/Content/Scripts/PIE-2.0beta1/PIE_IE678.js"></script><![endif]--></head><body><div class="page-container"><div class="operation">@Html.Partial("CRUDBtn", userInfo)</div><div class="table"><table id="table1" class="table table-border table-bordered table-bg table-hover"><thead><tr class="text-c"><th><input type="checkbox" name="" value=""></th><th>菜单名</th><th>请求路径</th><th>描述</th><th>添加时间</th><th>修改时间</th></tr></thead></table></div></div></body></html><script src="~/Content/Scripts/jquery-2.0.3.min.js"></script><script src="~/Content/Scripts/datatables/1.10.13/jquery.dataTables.min.js"></script><script src="~/Content/Scripts/layer/2.1/layer.js"></script><script src="~/Content/Scripts/My97DatePicker/WdatePicker.js"></script><script src="~/Content/Scripts/h-ui/js/H-ui.js"></script><script src="~/Content/Scripts/h-ui.admin/js/H-ui.admin.js"></script><script src="~/Content/Scripts/treegrid/js/jquery.treegrid.min.js"></script><script type="text/javascript">var table1 = null;$(function () {table1 = initializeTable();clickDeal();});/*点击处理*/function clickDeal() {var addBtn = $("#add");var deleteBtn = $("#delete");var editBtn = $("#edit");var viewBtn = $("#view");$("#search").click(function () {table1.ajax.reload();return false;});if (addBtn != null) {addBtn.click(function () {var title = $(this).text().substring(1).trim();var url = $(this).attr("url");layer_show(title, url, 600, 360);});}if (deleteBtn != null) {deleteBtn.click(function () {var idArr = [];var url = $(this).attr("url");$("input:checkbox[name=id]:checked").each(function () {var item = this;idArr.push($(item).val());});if (idArr.length == 0) {layer.msg("请⾄少选择⼀个选项", { icon: 2, time: 2000 });}else {layer.confirm('确认要删除吗?', function (index) {var loadIndex = layer.load();$.ajax({url: url,type: "post",data: { "idArrStr": idArr.toString() },dataType: "json",success: function (data) {if (data.Pass) {layer.close(loadIndex);layer.msg(data.Msg, { icon: 1, time: 2000 });table1.ajax.reload(null, false);} else {layer.msg(data.Msg, { icon: 1, time: 2000 });}},error: function (msg) {layer.msg(msg.status);}});});}});}if (editBtn != null) {editBtn.click(function () {var idArr = [];var title = $(this).text().substring(1).trim();var url = $(this).attr("url");$("input:checkbox[name=id]:checked").each(function () {var item = this;idArr.push($(item).val());});if (idArr.length != 1) {layer.msg("请选择⼀个选项", { icon: 2, time: 2000 });}else {url += "?id=" + idArr[0];layer_show(title, url, 600, 360);}});}if (viewBtn != null) {viewBtn.click(function () {var idArr = [];var title = $(this).text().substring(1).trim();var url = $(this).attr("url");$("input:checkbox[name=id]:checked").each(function () {var item = this;idArr.push($(item).val());});if (idArr.length != 1) {layer.msg("请选择⼀个选项", { icon: 2, time: 2000 });}else {url += "?id=" + idArr[0];layer_show(title, url, 600, 360);}});}}/*初始化table*/function initializeTable() {var table = $("#table1").DataTable({/****************************************表格数据加载****************************************************/"serverSide": true,"ajax": {//ajax请求数据源"url": "/Power/Manager/Search","type": "post","data": function (data) {//添加额外的数据给服务器}},"columns": [//列绑定{ "defaultContent": "" },{ "data": "PowerName" },{ "data": "Url" },{ "data": "Description" },{ "data": "AddTime" },{ "data": "ModifyTime" }],"columnDefs": [//列定义{"targets": [0],"data": "PowerId","render": function (data, type, full) {//全部列值可以通过full.列名获取,⼀般单个列值⽤data PS:这⾥的render是有多少列就执⾏多少次⽅法。
Ext.tree.Panel显示checkbox并且级联选择或者取消选择ext4,ext5 Ext.data.TreeStore如何显示复选框checkbox,勾选复选框checkbox时如何级联选中子节点的复选框。
ext4,ext5实现check tree级联选择源代码如下提示:checkchange事件参数node,5+返回的是Ext.data.TreeModel,ext4是Ext.data.NodeInterface对象-收缩JavaScript代码Ext.onReady(function () {store = Ext.create('Ext.data.TreeStore', { root: { expanded: tru e }, proxy: { type: 'ajax', url: 'data.json' } });Ext.create('Ext.tree.Panel', {listeners: {checkchange: function (node, checked, opts) {if (checked) checkParentNode(node.parentNode, checked);checkChildNode(node, checked);}},store: store,rootVisible: false,renderTo: document.body});});function checkChildNode(node, checked) {if (!node) return;node.set('checked', checked);node.eachChild(function (child) {checkChildNode(child, checked);});}function checkParentNode(node, checked) {if (!node) return;node.set('checked', checked);checkParentNode(node.parentNode);}data.json,Ext.tree.Panel显示复选框很简单,每个节点增加checked属性(布尔值)即可。
JS组件系列——⾃⼰动⼿扩展BootstrapTable的treegrid功能前⾔:上篇博主⾃⼰动⼿封装了下treegrid的功能,但毕竟那个组件只是⼀个单独针对树形表格做的,适⽤性还⽐较有限。
关注博主的园友应该知道,博主的博客⾥⾯写了很多bootstrapTable的扩展,今天打算在直接在bootstrapTable的基础上扩展⼀个treegrid的功能,很多长期关注博主博客的园友⼀直在问我怎么在bootstrapTable⾥⾯直接使⽤treegrid的功能,所以今天还是带来点福利。
有兴趣的可以捧个⼈场!⼀、效果预览全部折叠展开⼀级全部展开⼆、代码⽰例怎么样?效果还⾏吧。
给出js的源码供⼤家参考。
(function ($) {'use strict';var sprintf = function (str) {var args = arguments,flag = true,i = 1;str = str.replace(/%s/g, function () {var arg = args[i++];if (typeof arg === 'undefined') {flag = false;return '';}return arg;});return flag ? str : '';};var getFieldIndex = function (columns, field) {var index = -1;$.each(columns, function (i, column) {if (column.field === field) {index = i;return false;}return true;});return index;};var calculateObjectValue = function (self, name, args, defaultValue) {var func = name;if (typeof name === 'string') {var names = name.split('.');if (names.length > 1) {func = window;$.each(names, function (i, f) {func = func[f];});} else {func = window[name];}}if (typeof func === 'object') {return func;}if (typeof func === 'function') {return func.apply(self, args);}if (!func && typeof name === 'string' && sprintf.apply(this, [name].concat(args))) {return sprintf.apply(this, [name].concat(args));}return defaultValue;};var getItemField = function (item, field) {if (typeof field !== 'string' || item.hasOwnProperty(field)) {return item[field];}var props = field.split('.');for (var p in props) {value = value[props[p]];}return value;};var getParent = function (node, source, field) {var data = [];var items = $.grep(source, function (item, index) {return node.ParentId == item[field];});$.each(items, function (index, item) {data.splice(0, 0, item);var child = getParent(item, source, field);$.each(child, function (i, n) {data.splice(0, 0, n);});});return data;};var getChild = function (node, source, field) {var data = [];var items = $.grep(source, function (item, index) {return item.ParentId == node[field];});$.each(items, function (index, item) {data.push(item);var child = getChild(item, source, field);$.each(child, function (i, n) {data.push(n);});});return data;};//调⽤bootstrapTable组件的构造器得到对象var BootstrapTable = $.fn.bootstrapTable.Constructor,_initData = BootstrapTable.prototype.initData,_initPagination = BootstrapTable.prototype.initPagination,_initBody = BootstrapTable.prototype.initBody;//重写bootstrapTable的initData⽅法BootstrapTable.prototype.initData = function () {_initData.apply(this, Array.prototype.slice.apply(arguments));var that = this;if (that.options.treeView && this.data.length > 0) {var rows = [];var roots = $.grep(this.data, function (row, index) {return row.Level == that.options.treeRootLevel;});$.each(roots, function (index, item) {rows.push(item);var child = getChild(item, that.data, that.options.treeId);$.each(child, function (i, n) {if (that.options.treeCollapseAll) {n.hidden = true;}rows.push(n);});});that.options.data = that.data = rows;}};//重写bootstrapTable的initPagination⽅法BootstrapTable.prototype.initPagination = function () {//理论情况下,treegrid是不⽀持分页的,所以默认分页参数为false this.options.pagination = false;//调⽤“⽗类”的“虚⽅法”_initPagination.apply(this, Array.prototype.slice.apply(arguments)); };//重写bootstrapTable的initBody⽅法BootstrapTable.prototype.initBody = function (fixedScroll) { var that = this,html = [],data = this.getData();this.$body = this.$el.find('tbody');if (!this.$body.length) {this.$body = $('<tbody></tbody>').appendTo(this.$el);}if (!this.options.pagination || this.options.sidePagination === 'server') {this.pageFrom = 1;this.pageTo = data.length;}for (var i = this.pageFrom - 1; i < this.pageTo; i++) {var key,item = data[i],style = {},csses = [],data_ = '',attributes = {},htmlAttributes = [];if (item.hidden) continue;style = calculateObjectValue(this.options, this.options.rowStyle, [item, i], style);if (style && style.css) {for (key in style.css) {csses.push(key + ': ' + style.css[key]);}}attributes = calculateObjectValue(this.options,this.options.rowAttributes, [item, i], attributes);if (attributes) {for (key in attributes) {htmlAttributes.push(sprintf('%s="%s"', key, escapeHTML(attributes[key])));}}if (item._data && !$.isEmptyObject(item._data)) {$.each(item._data, function (k, v) {if (k === 'index') {return;}data_ += sprintf(' data-%s="%s"', k, v);});}html.push('<tr',sprintf(' %s', htmlAttributes.join(' ')),sprintf(' id="%s"', $.isArray(item) ? undefined : item._id),sprintf(' class="%s"', style.classes || ($.isArray(item) ? undefined : item._class)),sprintf(' data-index="%s"', i),sprintf(' data-uniqueid="%s"', item[this.options.uniqueId]),sprintf('%s', data_),'>');if (this.options.cardView) {html.push(sprintf('<td colspan="%s">', this.header.fields.length));}if (!this.options.cardView && this.options.detailView) {html.push('<td>','<a class="detail-icon" href="javascript:">',sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.detailOpen), '</a>','</td>');}$.each(this.header.fields, function (j, field) {var text = '',value = getItemField(item, field),type = '',cellStyle = {},id_ = '',class_ = that.header.classes[j],data_ = '',rowspan_ = '',title_ = '',column = that.columns[getFieldIndex(that.columns, field)];if (!column.visible) {return;}value = calculateObjectValue(column,that.header.formatters[j], [value, item, i], value);if (item['_' + field + '_id']) {id_ = sprintf(' id="%s"', item['_' + field + '_id']);}if (item['_' + field + '_class']) {class_ = sprintf(' class="%s"', item['_' + field + '_class']);}if (item['_' + field + '_rowspan']) {rowspan_ = sprintf(' rowspan="%s"', item['_' + field + '_rowspan']);}if (item['_' + field + '_title']) {title_ = sprintf(' title="%s"', item['_' + field + '_title']);}cellStyle = calculateObjectValue(that.header,that.header.cellStyles[j], [value, item, i], cellStyle);if (cellStyle.classes) {class_ = sprintf(' class="%s"', cellStyle.classes);}if (cellStyle.css) {var csses_ = [];for (var key in cellStyle.css) {csses_.push(key + ': ' + cellStyle.css[key]);}style = sprintf('style="%s"', csses_.concat(that.header.styles[j]).join('; '));}if (item['_' + field + '_data'] && !$.isEmptyObject(item['_' + field + '_data'])) {$.each(item['_' + field + '_data'], function (k, v) {if (k === 'index') {return;}data_ += sprintf(' data-%s="%s"', k, v);});}if (column.checkbox || column.radio) {type = column.checkbox ? 'checkbox' : type;type = column.radio ? 'radio' : type;text = [that.options.cardView ?'<div class="card-view">' : '<td class="bs-checkbox">','<input' +sprintf(' data-index="%s"', i) +sprintf(' name="%s"', that.options.selectItemName) +sprintf(' type="%s"', type) +sprintf(' value="%s"', item[that.options.idField]) +sprintf(' checked="%s"', value === true ||(value && value.checked) ? 'checked' : undefined) +sprintf(' disabled="%s"', !column.checkboxEnabled ||(value && value.disabled) ? 'disabled' : undefined) +' />',that.header.formatters[j] && typeof value === 'string' ? value : '',that.options.cardView ? '</div>' : '</td>'].join('');item[that.header.stateField] = value === true || (value && value.checked);} else {value = typeof value === 'undefined' || value === null ?that.options.undefinedText : value;var indent, icon;if (that.options.treeView && column.field == that.options.treeField) {var indent = item.Level == that.options.Level ? '' : sprintf('<span style="margin-left: %spx;"></span>', (item.Level - that.options.treeRootLevel) * 15);var child = $.grep(data, function (d, i) {return d.ParentId == item[that.options.treeId] && !d.hidden;});icon = sprintf('<span class="tree-icon %s" style="cursor: pointer; margin: 0px 5px;"></span>', child.length > 0 ? that.options.expandIcon : that.options.collapseIcon);//icon = sprintf('<span class="tree-icon %s" style="cursor: pointer; margin: 0px 5px;"></span>', child.length > 0 ? that.options.expandIcon : "");}text = that.options.cardView ? ['<div class="card-view">',that.options.showHeader ? sprintf('<span class="title" %s>%s</span>', style,getPropertyFromOther(that.columns, 'field', 'title', field)) : '',sprintf('<span class="value">%s</span>', value),'</div>'].join('') : [sprintf('<td%s %s %s %s %s %s>', id_, class_, style, data_, rowspan_, title_),indent,icon,value,'</td>'].join('');if (that.options.cardView && that.options.smartDisplay && value === '') {html.push(text);});if (this.options.cardView) {html.push('</td>');}html.push('</tr>');}if (!html.length) {html.push('<tr class="no-records-found">',sprintf('<td colspan="%s">%s</td>',this.$header.find('th').length, this.options.formatNoMatches()),'</tr>');}this.$body.html(html.join(''));if (!fixedScroll) {this.scrollTo(0);}this.$body.find('> tr[data-index] > td').off('click dblclick').on('click dblclick', function (e) {var $td = $(this),$tr = $td.parent(),item = that.data[$tr.data('index')],index = $td[0].cellIndex,field = that.header.fields[that.options.detailView && !that.options.cardView ? index - 1 : index], column = that.columns[getFieldIndex(that.columns, field)],value = getItemField(item, field);if ($td.find('.detail-icon').length) {return;}that.trigger(e.type === 'click' ? 'click-cell' : 'dbl-click-cell', field, value, item, $td);that.trigger(e.type === 'click' ? 'click-row' : 'dbl-click-row', item, $tr);if (e.type === 'click' && that.options.clickToSelect && column.clickToSelect) {var $selectItem = $tr.find(sprintf('[name="%s"]', that.options.selectItemName));if ($selectItem.length) {$selectItem[0].click();}}});this.$body.find('> tr[data-index] > td > .detail-icon').off('click').on('click', function () {debugger;var $this = $(this),$tr = $this.parent().parent(),index = $tr.data('index'),row = data[index];if ($tr.next().is('tr.detail-view')) {$this.find('i').attr('class', sprintf('%s %s', that.options.iconsPrefix, that.options.icons.detailOpen)); $tr.next().remove();that.trigger('collapse-row', index, row);} else {$this.find('i').attr('class', sprintf('%s %s', that.options.iconsPrefix, that.options.icons.detailClose)); $tr.after(sprintf('<tr class="detail-view"><td colspan="%s">%s</td></tr>',$tr.find('td').length, calculateObjectValue(that.options,that.options.detailFormatter, [index, row], '')));that.trigger('expand-row', index, row, $tr.next().find('td'));}that.resetView();});this.$body.find('> tr[data-index] > td > .tree-icon').off('click').on('click', function (e) {debugger;e.stopPropagation();var $this = $(this),$tr = $this.parent().parent(),index = $tr.data('index'),row = data[index];var icon = $(this);var child = getChild(data[index], data, that.options.treeId);$.each(child, function (i, c) {$.each(that.data, function (index, item) {if (item[that.options.treeId] == c[that.options.treeId]) {item.hidden = icon.hasClass(that.options.expandIcon);that.uncheck(index);});if (icon.hasClass(that.options.expandIcon)) {icon.removeClass(that.options.expandIcon).addClass(that.options.collapseIcon); } else {icon.removeClass(that.options.collapseIcon).addClass(that.options.expandIcon); }that.options.data = that.data;that.initBody(true);});this.$selectItem = this.$body.find(sprintf('[name="%s"]', this.options.selectItemName));this.$selectItem.off('click').on('click', function (event) {event.stopImmediatePropagation();var $this = $(this),checked = $this.prop('checked'),row = that.data[$this.data('index')];if (that.options.maintainSelected && $(this).is(':radio')) {$.each(that.options.data, function (i, row) {row[that.header.stateField] = false;});}row[that.header.stateField] = checked;if (that.options.singleSelect) {that.$selectItem.not(this).each(function () {that.data[$(this).data('index')][that.header.stateField] = false;});that.$selectItem.filter(':checked').not(this).prop('checked', false);}that.updateSelected();that.trigger(checked ? 'check' : 'uncheck', row, $this);});$.each(this.header.events, function (i, events) {if (!events) {return;}if (typeof events === 'string') {events = calculateObjectValue(null, events);}var field = that.header.fields[i],fieldIndex = $.inArray(field, that.getVisibleFields());if (that.options.detailView && !that.options.cardView) {fieldIndex += 1;}for (var key in events) {that.$body.find('tr').each(function () {var $tr = $(this),$td = $tr.find(that.options.cardView ? '.card-view' : 'td').eq(fieldIndex),index = key.indexOf(' '),name = key.substring(0, index),el = key.substring(index + 1),func = events[key];$td.find(el).off(name).on(name, function (e) {var index = $tr.data('index'),row = that.data[index],value = row[field];func.apply(this, [e, value, row, index]);});});}});this.updateSelected();this.resetView();this.trigger('post-body');};//给组件增加默认参数列表$.extend($.fn.bootstrapTable.defaults, {treeView: false,//treeView视图treeField: "id",//treeView视图字段treeRootLevel: 0,//根节点序号treeCollapseAll: false,//是否全部展开collapseIcon: "glyphicon glyphicon-chevron-right",//折叠样式expandIcon: "glyphicon glyphicon-chevron-down"//展开样式});})(jQuery);组件的使⽤如下:1、⾸先引⽤这个js⽂件。
treegrid级联勾选或深度级联勾选扩展:两种扩展先明确两个概念:1、级联勾选:不包括未加载的子节点2、深度级联勾选:包括未加载的子节点两种思路:1、扩展个新方法cascadeCheck,当需要进行级联勾选时,调用该方法进行级联勾选或不勾选。
2、扩展onLoadSuccess方法,添加一个自定义属性:cascadeCheck (级联)或deepCascadeCheck(深度级联),通过监听checkbox的click事件判断是否级联或深度级联来进行级联勾选或不勾选。
第一种扩展,因为是调用方法的,所以使用起来比较灵活,你可以在单击事件里使用,也可以在双击事件、右键菜单等里面使用;第二种扩展,因为是事件监听,只要设置了属性就会自动进行级联操作。
以下贴上两种扩展的代码:【第一种】扩展一个方法cascadeCheck/*** 扩展树表格级联勾选方法:* @param {Object} container* @param {Object} options* @return {TypeName}*/$.extend($.fn.treegrid.methods,{/*** 级联选择* @param {Object} target* @param {Object} param* param包括两个参数:* id:勾选的节点ID* deepCascade:是否深度级联* @return {TypeName}*/cascadeCheck : function(target,param){var opts = $.data(target[0],"treegrid").options;if(opts.singleSelect)return;var idField = opts.idField;//这里的idField其实就是API里方法的id参数var status = false;//用来标记当前节点的状态,true:勾选,false:未勾选var selectNodes =$(target).treegrid('getSelections');//获取当前选中项for(var i=0;i<selectNodes.length;i++){if(selectNodes[i][idField]==param.id)status = true;}//级联选择父节点selectParent(target[0],param.id,idField,status);selectChildren(target[0],param.id,idField,param.deepCascade,s tatus);/*** 级联选择父节点* @param {Object} target* @param {Object} id 节点ID* @param {Object} status 节点状态,true:勾选,false:未勾选* @return {TypeName}*/functionselectParent(target,id,idField,status){var parent =$(target).treegrid('getParent',id);if(parent){var parentId = parent[idField];if(status)$(target).treegrid('select',parentId);else$(target).treegrid('unselect',parentId);selectParent(target,parentId,idField,status);}}/*** 级联选择子节点* @param {Object} target* @param {Object} id 节点ID* @param {Object} deepCascade 是否深度级联* @param {Object} status 节点状态,true:勾选,false:未勾选* @return {TypeName}*/functionselectChildren(target,id,idField,deepCascade,status){//深度级联时先展开节点if(!status&&deepCascade)$(target).treegrid('expand',id);//根据ID获取下层孩子节点var children =$(target).treegrid('getChildren',id);for(var i=0;i<children.length;i++){var childId =children[i][idField];if(status)$(target).treegrid('select',childId);else$(target).treegrid('unselect',childId);selectChildren(target,childId,idField,deepCascade,status);//递归选择子节点}}}});该方法需要一个参数param={id:'节点id',//这里的id其实是所选行的idField列的值deepCascade:true //true:深度级联,false:级联}使用该方法的时候需要注意:1、singleSelect=false,明显要支持多选2、{field:'ck',checkbox:true},当然勾选框也不能少3、idField需要设置,不然找不着id了。
idField的意义就不多说了~使用示例:$('#test').treegrid({...idField:'code',//需设置treeField:'code',singleSelect:false,//需设置columns:[[{field:'ck',checkbox:true},//需设置{title:'Code',field:'code',width:200},....]],onClickRow:function(row){//级联选择$(this).treegrid('cascadeCheck',{id:row.code, //节点IDdeepCascade:true //深度级联});}});【第二种】扩展treegrid的onLoadSuccess事件,代码如下:/*** 扩展树表格级联选择(点击checkbox才生效):* 自定义两个属性:* cascadeCheck :普通级联(不包括未加载的子节点)* deepCascadeCheck :深度级联(包括未加载的子节点)*/$.extend($.fn.treegrid.defaults,{onLoadSuccess : function() {var target = $(this);var opts = $.data(this, "treegrid").options;var panel = $(this).datagrid("getPanel");var gridBody = panel.find("div.datagrid-body");var idField = opts.idField;//这里的idField其实就是API里方法的id参数gridBody.find("div.datagrid-cell-checkinput[type=checkbox]").unbind(".treegrid").click(function(e){if(opts.singleSelect) return;//单选不管if(opts.cascadeCheck||opts.deepCascadeCheck){varid=$(this).parent().parent().parent().attr("node-id");var status = false;if($(this).attr("checked")) status = true;//级联选择父节点selectParent(target,id,idField,status);selectChildren(target,id,idField,opts.deepCascadeCheck,status );/*** 级联选择父节点* @param {Object} target* @param {Object} id 节点ID* @param {Object} status 节点状态,true:勾选,false:未勾选* @return {TypeName}*/functionselectParent(target,id,idField,status){var parent =target.treegrid('getParent',id);if(parent){var parentId = parent[idField];if(status)target.treegrid('select',parentId);elsetarget.treegrid('unselect',parentId);selectParent(target,parentId,idField,status);}}/*** 级联选择子节点* @param {Object} target* @param {Object} id 节点ID* @param {Object} deepCascade 是否深度级联* @param {Object} status 节点状态,true:勾选,false:未勾选* @return {TypeName}*/functionselectChildren(target,id,idField,deepCascade,status){//深度级联时先展开节点if(status&&deepCascade)target.treegrid('expand',id);//根据ID获取下层孩子节点var children =target.treegrid('getChildren',id);for(vari=0;i<children.length;i++){var childId = children[i][idField];if(status)target.treegrid('select',childId);elsetarget.treegrid('unselect',childId);selectChildren(target,childId,idField,deepCascade,status);//递归选择子节点}}}e.stopPropagation();//停止事件传播});}});使用该扩展的时候需要注意:1、singleSelect=false,明显要支持多选2、级联是还需要配置属性(自定义属性,API没有):cascadeCheck :true //普通级联(不包括未加载的子节点)deepCascadeCheck :true //深度级联(包括未加载的子节点)3、{field:'ck',checkbox:true},当然勾选框也不能少4、idField同样需要设置,不然找不着id了。