项目开发,临时的一个需求,将8000条数据整成树形机构的下拉控件,网上找了资料,可以使用easyUI的combotree实现
看了官网资料,combotree需要的数据必须是json数据,json的key为 id,text,children,用的是jsonarray生成json数据
例如:{'id':1000,"text":root,"children":[{"id":1001,"text":root1,"children":[{"id":1002,"text":root2,"children":[{}]}]}]}
根节点下面有多个子节点的结构
这样的话:就是一个map容器里面放置List<Map>的结构
后台代码
package flink.net.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.util.WebUtils;
import com.ylink.mfo.action.form.UserInfo;
import com.ylink.mfo.msg.rsp.RspA9011;
import flink.consant.Constants;
public class MyBranchUtils {
//获取当前用户所在机构的所有子机构信息
//参数list是机构信息所有记录
public static Map<String, Object> getCombotreeInfo(List<RspA9011> list,HttpServletRequest request){
Map<String,Object> map = new HashMap<String, Object>();
UserInfo userInfo = (UserInfo)WebUtils.getSessionAttribute(request, Constants.SESSION_USER);
for (RspA9011 rspA9011 : list) {
if(rspA9011.getBranch_id().equals(userInfo.getBranchId())){
map.put("id", rspA9011.getBranch_id());
map.put("text", rspA9011.getBranch_name());
map.put("children", MyBranchUtils.getChildrenRoleInfo(rspA9011.getBranch_id(), list));
}
}
return map;
}
//通过父机构号递归获取子孙机构
public static List<Map<String,Object>> getChildrenRoleInfo(String parentId,List<RspA9011> list){
List<Map<String,Object>> total = new ArrayList<Map<String,Object>>();
for (RspA9011 rspA9011 : list) {
if(rspA9011.getParent_branch_id().equals(parentId)){
Map<String,Object> map = new HashMap<String, Object>();
map.put("id", rspA9011.getBranch_id());
map.put("text", rspA9011.getBranch_name());
map.put("children", getChildrenRoleInfo(rspA9011.getBranch_id(), list));
total.add(map);
}
}
return total;
}
}
说明1:RspA9001类,是一个对应数据库表(机构号,当前机构名称,父机构号)的实体,实体的属性定义如下:
branch_id : 机构号
branch_name: 机构名称
parent_branch_id: 父机构号
说明2: 方法getCombotreeInfo有两个参数list是机构信息的所有记录数,request请求用来获取当前用户的机构号,返回的是Map<List>结构的数据,传回到前台时候,需要用Json工具类转json数据。
写回json数据,原生的servelet方式,BusinessMap.BRANCH_INFO_LIST是所有机构记录的list
response.setContentType("text/javascript;charset=utf-8");
response.setCharacterEncoding("utf-8");
JSONArray fromObject = new JSONArray();
if(BusinessMap.BRANCH_INFO_LIST.size()>0){
Map<String, Object> combotreeInfo = MyBranchUtils.getCombotreeInfo(BusinessMap.BRANCH_INFO_LIST, request);
fromObject = JSONArray.fromObject(combotreeInfo);
}
response.getWriter().print(fromObject);
response.getWriter().flush();
response.getWriter().close();
return null;
前台js加载数据
页面:
<select id="branch_id" class="easyui-combotree" method="get" style="width: 160px;"></select>
ajax获取数据
和后台使用ajax交互,因为多个页面用到了机构下拉列表,所以就在主页面加载时候的,请求了一次后台,缓存在主页面上,后面子页面都从主页面取值,当然,也可以ajax获取成功后,初始化combotree
//载入json机构信息
var loginBranchInfo;
$.ajax({
type:'get',
url:CONTEXT_PATH+'/sysConfig.do?action=jsonBranchInfo',
dataType:'json',
success:function(data){
loginBranchInfo = data;
//这里也可以直接初始化combotree
},
error:function(){
alert('机构信息加载失败');
}
});
子页面初始化combotree:
子页面获取主页面数据
var jsonBranchData = window.parent.loginBranchInfo;
$('#branch_id').combotree
({
data:jsonBranchData,
valueField: 'id',
textField: 'text',
required: false,
editable: true,
onLoadSuccess: function (node, data) {
$('#branch_id').combotree('tree').tree("collapseAll");
}
});
其他初始化方式
官网上的方式:将上面的data改为一个url,填入后台一个地址,返回的是json数据就行
其他功能实现
1. 实现数据回显
如果是页面回显,触发onLoadSuccess事件,可以遍历所有节点,只要节点的值和param.[参数]相同,就选中这个节点,
在触发onSelect事件,设置选中的文本是节点的text,这个有点问题,只能看,不能再次点击,如果再次点击的话,combotree的值是空的。
不过,应该可以这样,onSelect 后将具体的值,赋给一个隐藏的input,使用这个input提交。
onLoadSuccess: function (node, data) {
//回显时,默认选中的值
var root = $("#branch_id").combotree('tree').tree('getRoot');
var childrens = $("#branch_id").combotree('tree').tree('getChildren',root.target);
childrens.push(root);
for(var i=0;i<childrens.length;i++){
if(childrens[i].id == '${param.branchId}'){
var thisnode = $("#branch_id").combotree('tree').tree('find',childrens[i].id);
$("#branch_id").combotree('tree').tree('select',thisnode.target);
}
}
$('#branch_id').combotree('tree').tree("collapseAll");
},
onSelect:function(node){
$("#branch_id").combotree('setText',node.text);
}
2. 输入框输入,能够查询到对应的子节点
要实现输入select框查询到对应的节点,需要将editable改为true,网上找了些js方法实现,实现如下
$(".combo-text").bind("input propertychange", function() {
$('#branch_id').combotree('tree').tree("search",$(this).val());
if($(this).val()=="" || null==$(this).val()){
$('#branch_id').combotree('tree').tree("expandAll");
}
});
search方法定义,网上找的
(function($) {
$.extend($.fn.tree.methods, {
search: function(jqTree, searchText) {
// easyui tree的tree对象。可以通过tree.methodName(jqTree)方式调用easyui tree的方法
var tree = this;
// 获取所有的树节点
var nodeList = getAllNodes(jqTree, tree);
// 如果没有搜索条件,则展示所有树节点
searchText = $.trim(searchText);
if (searchText == "") {
for (var i=0; i<nodeList.length; i++){
$(".tree-node-targeted", nodeList[i].target).removeClass("tree-node-targeted");
$(nodeList[i].target).show();
}
// 展开已选择的节点(如果之前选择了)
var selectedNode = tree.getSelected(jqTree);
if (selectedNode) {
tree.expandTo(jqTree, selectedNode.target);
}
return;
}
// 搜索匹配的节点并高亮显示
var matchedNodeList = [];
if (nodeList && nodeList.length>0) {
var node = null;
for (var i=0; i<nodeList.length; i++){
node = nodeList[i];
if (isMatch(searchText, node.text)) {
matchedNodeList.push(node);
}
}
// 隐藏所有节点
for (var i=0; i<nodeList.length; i++){
$(".tree-node-targeted", nodeList[i].target).removeClass("tree-node-targeted");
$(nodeList[i].target).hide();
}
// 折叠所有节点
tree.collapseAll(jqTree);
// 展示所有匹配的节点以及父节点
for (var i=0; i<matchedNodeList.length; i++){
showMatchedNode(jqTree, tree, matchedNodeList[i]);
}
}
},
showChildren: function(jqTree, node) {
// easyui tree的tree对象。可以通过tree.methodName(jqTree)方式调用easyui tree的方法
var tree = this;
// 展示子节点
if (!tree.isLeaf(jqTree, node.target)) {
var children = tree.getChildren(jqTree, node.target);
if (children && children.length>0) {
for (var i=0; i<nodeList.length; i++){
if ($(children[i].target).is(":hidden")) {
$(children[i].target).show();
}
}
}
}
},
scrollTo:function(jqTree, param) {
// easyui tree的tree对象。可以通过tree.methodName(jqTree)方式调用easyui tree的方法
var tree = this;
// 如果node为空,则获取当前选中的node
var targetNode = param && param.targetNode ? param.targetNode : tree.getSelected(jqTree);
if (targetNode != null) {
// 判断节点是否在可视区域
var root = tree.getRoot(jqTree);
var $targetNode = $(targetNode.target);
var container = param && param.treeContainer ? param.treeContainer : jqTree.parent();
var containerH = container.height();
var nodeOffsetHeight = $targetNode.offset().top - container.offset().top;
if (nodeOffsetHeight > (containerH - 30)) {
var scrollHeight = container.scrollTop() + nodeOffsetHeight - containerH + 30;
container.scrollTop(scrollHeight);
}
}
}
});
function showMatchedNode(jqTree, tree, node) {
// 展示所有父节点
$(node.target).show();
$(".tree-title", node.target).addClass("tree-node-targeted");
var pNode = node;
while ((pNode = tree.getParent(jqTree, pNode.target))) {
$(pNode.target).show();
}
// 展开到该节点
tree.expandTo(jqTree, node.target);
// 如果是非叶子节点,需折叠该节点的所有子节点
if (!tree.isLeaf(jqTree, node.target)) {
tree.collapse(jqTree, node.target);
}
}
function isMatch(searchText, targetText) {
return $.trim(targetText)!="" && targetText.indexOf(searchText)!=-1;
}
function getAllNodes(jqTree, tree) {
var allNodeList = jqTree.data("allNodeList");
if (!allNodeList) {
var roots = tree.getRoots(jqTree);
allNodeList = getChildNodeList(jqTree, tree, roots);
jqTree.data("allNodeList", allNodeList);
}
return allNodeList;
}
function getChildNodeList(jqTree, tree, nodes) {
var childNodeList = [];
if (nodes && nodes.length>0) {
var node = null;
for (var i=0; i<nodes.length; i++){
node = nodes[i];
childNodeList.push(node);
if (!tree.isLeaf(jqTree, node.target)) {
var children = tree.getChildren(jqTree, node.target);
childNodeList = childNodeList.concat(getChildNodeList(jqTree, tree, children));
}
}
}
return childNodeList;
}
})(jQuery);