前言
这是在使用easyui的过程中遇到的问题。出错的原因还是自己粗心,最主要的是对easyui不熟悉,没能很好理解tree的加载方式。写下这篇文章来记录下,方便以后需要时查看。
补充:树形菜单和树形下拉框几乎一样。都是通过url属性加载数据。唯一的区别就是树形菜单是tree控件,而树形下拉框是combotree控件,用法一样。
问题及其解决
easyui的树形菜单的一个问题,如图:
理想的情况展开父节点时出现的应该是其子节点。但是现在不知道为什么,展开的节点还是父节点本身,一直展开,一直都是这个节点。
之所以会出现这个问题,主要还是对easyui不熟悉和不理解。
一开始,我的前端代码是这样的:
$('#wu-category-tree').tree({
url:'/dept/getTree',
});
然后显示的结果是这样:
但是,展开a部门,出现的还是a部门。
虽然这里能把树形菜单初始化显示出来。但是其实对easyui的tree还是不理解。譬如上面写的前端代码,我并没有传递参数啊。
我的疑惑是,怎么让节点id作为url的参数传到后台啊。看了文档,没找到答案。
上网查了一下,看到这个代码:
$(function(){
$("#tree").tree({
method:"get",
url:"test/tree",//这里写用来调用的后台的方法
onBeforeExpand:function(node,param){
url:"test/tree?pid="+node.id;
//在节点展开之前触发,这里将单击节点的id传到后台,就可以查出所有该节点的子节点,然后展示
}
});
});
试了一下,加上onBeforeExpand事件,发现还是不行。
又试了直接在浏览器的地址栏上发起请求:
http://localhost:8080/dept/getTree?parentId=31
发现是能返回正常的数据的:
[{"id":32,"text":"b部门","checked":false,"children":null,"state":"closed"},
{"id":33,"text":"c部门","checked":false,"children":null,"state":"closed"},
{"id":34,"text":"d部门","checked":false,"children":null,"state":"open"}]
根据以往经验,每次在浏览器地址栏访问正常而在通过网站访问却不行,都是controller层出现问题!先看看发起请求时前台传到后台的参数:
传的是id字段!!!
突然记起控制台sql语句说我传了两个参数,并且查询到的结果是一条。当时没多留意,只是觉得很奇怪,应该是只传了一个parentId才对啊。
这时才想明白问题是出在controller方法:
@RequestMapping(value = "/getTree")
@ResponseBody
public List getTree(Dept dept){
logger.info("前台传来的参数id为"+dept.getId());
if(dept.getParentId()==null)
dept.setParentId(0);
return deptService.getTree(dept);
}
controller方法这里,前台传来的是id字段,我傻了,理所当然的认为传来的是parentId字段。结果我对parentId字段进行验证,如果为null,则设置为0。从而,导致在展开的时候传递到后台的id是31,而parentId为0。因此查询出来的一直都是a部门。
找到问题后,就很好改了:
@RequestMapping(value = "/getTree")
@ResponseBody
public List getTree(Integer id){
Dept dept = new Dept();
if(id==null)
dept.setParentId(0);
else
dept.setParentId(id);
return deptService.getTree(dept);
}
收获
树形菜单的加载:
$('#wu-category-tree').tree({
url:'/dept/getTree',
});
easyui很强大,通过这一句,只要后台传来的数据正确,就能加载自动加载出树形菜单。
我一开始就是很疑惑,我要怎么传id啊。我要怎样在展开时再次发起请求。看了文档,没找到答案。原来,在展开父节点时,会自动将该节点的id值作为参数发起请求,获取到数据后,自动加载出子树菜单。
代码记录
serviceImpl
(核心)serviceImpl层,实现数据的封装:
public List getTree(Dept dept){
List<TreeDTO> dtoList = new ArrayList<TreeDTO>();//用来存放子节点
List<Dept> deptList = deptDao.query(dept,null,null);//dept对象的有效数据是parentId,即query方法实现的是找出指定parentId的记录
if(deptList==null || deptList.size()==0)
return null;
for(Dept temp:deptList){//处理每个子节点
TreeDTO<Dept> td = new TreeDTO<Dept>(temp.getId(),temp.getName());//每个子节点都封装成dto对象
Dept deptWithParentId = new Dept();//作为query方法的参数
deptWithParentId.setParentId(temp.getId());//该参数只设置了parentId属性
List<Dept> childrenList = deptDao.query(deptWithParentId,null,null);//调用该方法,为的是查看该节点是否有子节点
if(childrenList.size()>0)
td.setState("closed");//td.setState("colsed");//一开始写错了,导致无法展开和折叠
else
td.setState("open");//叶子节点,得将status属性设置为open,表示其已经是展开了的
dtoList.add(td);//最后把子节点放到list中
}
return dtoList;//返回list
}
query方法
(我使用的是MyBatis)
Dao接口方法:
/**
* 根据参数进行查询,得到相关部门的列表
* @param dept
* @param offset
* @param limit
* @return
*/
List<Dept> query(@Param("dept") Dept dept,@Param("offset") Integer offset,@Param("limit") Integer limit);
mapper.xml:
<select id="query" resultType="Dept">
SELECT * FROM dept_inf
<where>
1=1
<if test="dept.id != null">
AND id = #{dept.id}
</if>
<if test="dept.name != null">
AND name = #{dept.name}
</if>
<if test="dept.remark != null">
AND remark = #{dept.remark}
</if>
<if test="dept.parentId != null">
AND parent_id = #{dept.parentId}
</if>
</where>
<if test="offset !=null">
limit #{offset},#{limit}
</if>
</select>
Bean
public class Dept implements Serializable{
private Integer id;
private String name;//部门名称
private String remark;//详细描述
private Integer parentId;//直属上级部门
//省略getter方法和setter方法
}
TreeDTO
(之所以要有这个类,是为了配了easyui的使用,easyui要求你传回这种格式的数据)
public class TreeDTO<E> {//使用泛型是因为职位类也需要用到树形结果,通过泛型就能通用了
private int id;
private String text;
private boolean checked;
private List<TreeDTO> children;
private String state;
//省略getter方法和setter方法
}
controller方法
@RequestMapping(value = "/getTree")
@ResponseBody
public List getTree(Integer id){
Dept dept = new Dept();
if(id==null) //是判断id字段!传来的id字段要作为parentId条件来查询
dept.setParentId(0);
else
dept.setParentId(id);
return deptService.getTree(dept);
}
前端代码
<div data-options="region:'west',border:true,split:true," title="部门选择" style="width:200px; padding:5px;">
<ul id="wu-category-tree" class="easyui-tree"></ul>
</div>
$('#wu-category-tree').tree({
url:'/dept/getTree',
animate:true,
});