本文将为您详细讲解ExtJs树控件的使用,如有不足之处,欢迎您指正,我的QQ:1113905744,
文章中用到的所有代码将在文末附上!
效果图有两种
带复选框与不带复选框的树,在下文中有讲解,注意留意。
注:原始数据中有checked属性则有复选框,没有checked属性则没有复选框
- 不带复选框
- 带复选框
调用方式:
详解:
- 创建一个基类,该类为ExtJs封装好的类,里面包含有:点击父节点选中全部子节点,复选框回显等方法 。直接拿来用就行:
- 创建树控件 :1. 创建时的类名要以上一步的基类类名为准 2. 数据源(下一步讲解)
- 创建数据源,树形控件的关键。从后台传来的树形结构的数据,我会分几步做详细讲解,首先上效果图:
接下来为大家详细说明下后台的数据如何整理为嵌套形式的数据,图片如下:
- 整理树形结构的字段:dept_code 每三位代表一级树,六位为第二级树,依次递增
- 整理数据方法如下 代码我会放到文章末。
- 往查到的数据中插入两个属性:leaf,checked ;嵌套的编码:就是你在数据库中定义的三位一级的编码。 下面这个方法只需要修改我在图中标注的那两个地方就可以了
代码:
前台代码:
基类:
Ext.define('Ext.ux.tree.CustomeTreePanel', {
extend : 'Ext.tree.Panel',
rootVisible : false,
useArrows : true, //箭头样式
frame : false, //圆角
header : false,
indeterminateCls : 'x-tree-checkbox-indeterminate',
width : 350,
height : 200,
initComponent:function(){
var me = this;
me.callParent();
},
listeners : {
checkchange : function(node, checked) {
var me = this;
me.setChildrenCheckedStatus(node, checked);
me.updateParentCheckedStatus(node, checked);
},
collapse:function(p){
}
},
setChildrenCheckedStatus : function(node, check) {
var me = this;
var len = node.childNodes.length;
if (len <= 0 || node.get('disabled') === true) {
if (node.get('disabled') === false)
node.set('checked', check);
return node.get('checked') ? 1 : -1;
} else {
var sumcount = 0;
for (var index = 0; index < len; index++) {
var subnode = node.childNodes[index];
subnode.set('checked', check)
sumcount = sumcount+ me.setChildrenCheckedStatus(subnode, check);
}
if (len === Math.abs(sumcount)) {
me.unsetThirdState(node);
node.set('checked', check);
return node.get('checked') ? 1 : -1;
} else {
me.setThirdState(node);
return 0;
}
}
},
updateParentCheckedStatus : function(node, check) {
var me = this;
var nodeparent = node.parentNode;
if (!nodeparent) {
return;
} else {
var len = nodeparent.childNodes.length;
var sumcount = 0;
for (var index = 0; index < len; index++) {
var subnode = nodeparent.childNodes[index];
if (me.isThirdState(subnode)) {
sumcount = sumcount + 0;
} else {
if (subnode.get('checked')) {
sumcount = sumcount + 1;
} else {
sumcount = sumcount - 1;
}
}
}
if (len === Math.abs(sumcount)) {
me.unsetThirdState(nodeparent);
nodeparent.set('checked', check);
} else {
me.setThirdState(nodeparent);
}
me.updateParentCheckedStatus(nodeparent, check);
}
},
isThirdState : function(node) {
return node.get('cls') == this.indeterminateCls;
},
setThirdState : function(node) {
node.set('cls', this.indeterminateCls);
node.set('checked', true);
},
unsetThirdState : function(node) {
node.set('cls', '');
},
getLeafIdSelections : function() {
var me = this;
try {
var tree_selections = me.getView().getChecked(), result = [];
Ext.Array.each(tree_selections, function(rec) {
console.log(rec);
if (rec.get('text')!="Root") {
result.push(rec.get('id')/* ,rec.get('text') */);
}
});
return result;
} catch (e) {
debug('[error in accessPanel getSelections]');
debug(e);
}
},
setSelections : function(codes) {
var ids = codes.split(",");
var me = this;
if (ids[0] && ids[0]['id']) {
ids = Ext.Array.pluck(ids, 'id');
}
me.getRootNode().cascadeBy(
function() {
var currNode = this;
if (currNode.get('leaf')) {
currNode.set('checked',
ids.indexOf(currNode.get('id')) > -1);
me.updateParentCheckedStatus(currNode, ids
.indexOf(currNode.get('id')) > -1);
}
});
},
});
树控件:
bankSysEditTreePanel = Ext.create('Ext.ux.tree.CustomeTreePanel',{
title : "机构列表", //树控件名称
expanded:true, //默认展开树节点 没效果 需要优化一下
rootVisible:false, //是否显示root节点
scrollable: 'y', //滚动条
animScroll:true,//动画效果
store: userBankTreeStore, //调用的数据源
width : '100%',
height : '100%',
border : true,
animCollapse : true,
animate : true,
listeners:{ //监听器
}
});
数据源
var userBankTreeStore;
userBankTreeStore = Ext.create('Ext.data.TreeStore', {
fields: ["bank_name", "bank_id"], //Model
autoLoad : true,
pageSize : 15,
sorters : { //排序
property : 'bank_name',
direction : 'ASC'
},
clearOnLoad : true,
defaultRootId : '-1',
proxy : {
type : 'ajax',
url : getServerHttp() +"/nh-bank/cp/bank/bankList" , //后台接口路径
reader:{
type:'json',
},
},
root:{
expanded:true,
},
autoLoad:false
});
后台代码:
接口方法:
@ApiOperation(value = "树形机构")
@GetMapping("/bankListTo")
public JSONArray bankListTo() {
List<Map<String,Object>> banklist = bankService.allbank(); //查询要整理的原始数据
JSONArray result = JSONArray.parseArray(TreeTools.turnListToTree_bankAdd(banklist)); //整理为嵌套形式
return result;
}
将leaf,checked属性打入原始数据的方法:
public static List<Map<String, Object>> handleTree_bank(List<Map<String, Object>> menuList, boolean isChecked) {
for (Map<String, Object> map : menuList) {
map.put("id", map.get("dept_code"));
map.put("iconCls", map.get("url"));
map.put("text", map.get("bank_name"));
map.put("leaf", true);
if (isChecked) {
map.put("checked", false);
}
}
将数据整理成树结构:
@SuppressWarnings("unchecked")
public static String turnListToTree_bank(List<Map<String, Object>> menuList, boolean isChecked) {
// TODO 转换List为树形结构
menuList = handleTree_bank(menuList, isChecked);
List<Map<String, Object>> nodeList = new ArrayList<Map<String, Object>>();
for (Map<String, Object> node1 : menuList) {
String node1_code = (String) node1.get("dept_code");
String node1_parent_code = node1_code.substring(0, node1_code.length() - 3);
boolean mark = false;
for (Map<String, Object> node2 : menuList) {
String node2_code = (String) node2.get("dept_code");
if (node1_parent_code != null && node1_parent_code.equals(node2_code)) {
mark = true;
if (node2.get("children") == null) {
node2.put("children", new ArrayList<Map<String, Object>>());
}
((List<Map<String, Object>>) node2.get("children")).add(node1);
node2.put("leaf", false);
if (!isChecked) {
node2.put("expanded", true);
}
break;
}
}
if (!mark) {
nodeList.add(node1);
}
}
return JsonUtil.toJson(nodeList);
}
附上一些工作中踩过的坑:
- 保存树节点:红线标注的方法可以在上文中的基类中找到, 调用(树控件名.方法名)
2.树节点回显:用于回显的数据为逗号分隔的字符串,也就是上文中用于整理嵌套树结构的编码
代码如下:
function myEdit(kid) {
var me = this;
Ext.Ajax.request({
url : getServerHttp() +"/nh-bank/cp/roleAuth/edit_form?kid=" + kid,
success : function(response) {
var json = Ext.JSON.decode(response.responseText);
if(json){
me.showEditPanel(json.result);
}
// 列表树回显数据
window.EditTreePanel.setSelections(json.result.roleAuths); //括号中的数据为逗号分隔的字符串
},
failure : function(response) {
Ext.Msg.alert("提示", "操作失败!");
}
});
}// #myEdit