【原】无脑操作:EasyUI Tree实现左键只选择叶子节点、右键浮动菜单实现增删改
Easyui中的Tree组件使用频率颇高,经常遇到的需求如下:
1、在树形结构上,只有叶子节点才能被选中,其他节点不能被选中;
2、在叶子节点上右键出现浮动菜单实现新增、删除、修改操作;
3、在非叶子节点上右键出现浮动菜单实现新增、修改操作。
------------------------------------------------------------------------------------------------------------------
实现方法如下:
1、搭建测试环境(可以参考前文:【原】无脑操作:IDEA + maven + SpringBoot + JPA + EasyUI实现CRUD及分页)
2、建库建表
DROP TABLE biz_department;
CREATE TABLE biz_department
(
departmentid INT AUTO_INCREMENT PRIMARY KEY COMMENT '部门编号',
departmentpid INT NOT NULL COMMENT '部门父编号',
departmentname VARCHAR(10) NOT NULL COMMENT '部门名称'
) ENGINE=INNODB COMMENT='部门信息';
INSERT INTO biz_department VALUES
(NULL, 0, '总部'),
(NULL, 1, '上海分公司'), (NULL, 1, '安徽分公司'),
(NULL, 3, '合肥办事处'), (NULL, 3, '铜陵办事处');
3、创建实体类 Department.java
@Entity
@Table(name = "biz_department")
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "departmentid")
private Integer departmentid;
@Column(name = "departmentpid")
private Integer departmentpid;
@Column(name = "departmentname")
private String departmentname; public Department() {
} public Department(Integer departmentpid, String departmentname) {
this.departmentpid = departmentpid;
this.departmentname = departmentname;
} public Integer getDepartmentid() {
return departmentid;
} public void setDepartmentid(Integer departmentid) {
this.departmentid = departmentid;
} public Integer getDepartmentpid() {
return departmentpid;
} public void setDepartmentpid(Integer departmentpid) {
this.departmentpid = departmentpid;
} public String getDepartmentname() {
return departmentname;
} public void setDepartmentname(String departmentname) {
this.departmentname = departmentname;
}
}
4、编写DAO接口 DepartmentDao.java
/**
* 因为需要使用分页和条件查询,所以从JpaRepository接口 和 JpaSpecificationExecutor接口继承
*/
public interface DepartmentDao extends JpaRepository<Department, Integer>, JpaSpecificationExecutor<Department> { }
5、编写工具类 TreeNode.java 和 TreeUtil.java
/**
* EasyUI Tree的封装类
*/
public class TreeNode {
private Integer id; // 节点的 id
private Integer parentId; // 父节点id,java生成树时使用
private String text; // 显示的节点文字。
private String iconCls; // 节点图标样式 "iconCls":"icon-save", "iconCls":"icon-ok", 等
private String state; // 节点状态, 'open' 或 'closed',默认是 'open'。当设为 'closed' 时,此节点有子节点,并且将从远程站点加载它们。
private String flag; // 节点类型
private Integer trueId; // 应用系统真实 id
private boolean checked; // 指示节点是否被选中。
private LinkedHashMap<?, ?> attributes; // 给一个节点追加的自定义属性。
private List<TreeNode> children; // 定义了一些子节点的节点数组。
private String url; // 扩展属性url public Integer getTrueId() {
return trueId;
} public void setTrueId(Integer trueId) {
this.trueId = trueId;
} public String getFlag() {
return flag;
} public void setFlag(String flag) {
this.flag = flag;
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public Integer getParentId() {
return parentId;
} public void setParentId(Integer parentId) {
this.parentId = parentId;
} public String getText() {
return text;
} public void setText(String text) {
this.text = text;
} public String getIconCls() {
return iconCls;
} public void setIconCls(String iconCls) {
this.iconCls = iconCls;
} public String getState() {
return state;
} public void setState(String state) {
this.state = state;
} public boolean isChecked() {
return checked;
} public void setChecked(boolean checked) {
this.checked = checked;
} public LinkedHashMap<?, ?> getAttributes() {
return attributes;
} public void setAttributes(LinkedHashMap<?, ?> attributes) {
this.attributes = attributes;
} public List<TreeNode> getChildren() {
return children;
} public void setChildren(List<TreeNode> children) {
this.children = children;
} public String getUrl() {
return url;
} public void setUrl(String url) {
this.url = url;
}
}
/**
* 树工具类
*/
public class TreeUtil {
/**
* Tree装配方法
*
* @param tempTreeNodes
* @param treeNodes
* @return
*/
public static List<TreeNode> Assemble(List<TreeNode> tempTreeNodes, List<TreeNode> treeNodes) {
if (tempTreeNodes != null) {
Map<Integer, TreeNode> map = new LinkedHashMap<>();
for (TreeNode tn : tempTreeNodes) {
map.put(tn.getId(), tn);
} TreeNode treeNode;
TreeNode pTreeNode;
for (Integer id : map.keySet()) {
treeNode = map.get(id);
if (treeNode.getParentId() == 0) {
treeNodes.add(treeNode);
} else {
pTreeNode = map.get(treeNode.getParentId());
List<TreeNode> children = pTreeNode.getChildren();
if (children != null) {
children.add(treeNode);
} else {
children = new ArrayList();
children.add(treeNode);
pTreeNode.setChildren(children);
}
}
}
} return treeNodes;
}
}
6、规划控制器 DepartmentController.java
@Controller
@RequestMapping("/department")
public class DepartmentController {
@Autowired
private DepartmentDao departmentDao; @RequestMapping("/view")
public String view() {
// 跳转至【资源管理】页面
return "department";
} @RequestMapping("/tree")
@ResponseBody
public String tree() {
List<Department> list = departmentDao.findAll();
List<TreeNode> tempTreeNodes = new ArrayList();
List<TreeNode> treeNodes = new ArrayList(); // 组装Easyui的Tree必须要有id、parentId、text属性,转换之
for (Department department : list) {
TreeNode tempTreeNode = new TreeNode();
tempTreeNode.setId(department.getDepartmentid());
tempTreeNode.setParentId(department.getDepartmentpid());
tempTreeNode.setText(department.getDepartmentname());
tempTreeNodes.add(tempTreeNode);
} return JSONObject.toJSON(TreeUtil.Assemble(tempTreeNodes, treeNodes)).toString();
} @RequestMapping("/saveNode")
@ResponseBody
public Map<String, Object> saveNode(Integer departmentpid, String departmentname) {
Department model = new Department();
model.setDepartmentpid(departmentpid);
model.setDepartmentname(departmentname); Map<String, Object> resultMap = new HashMap<>();
departmentDao.save(model);
resultMap.put("success", true);
return resultMap;
} @RequestMapping("/updateNode")
@ResponseBody
public Map<String, Object> updateNode(Department model) {
Map<String, Object> resultMap = new HashMap<>();
departmentDao.save(model);
resultMap.put("success", true);
return resultMap;
} @RequestMapping("/deleteNode")
@ResponseBody
public Map<String, Object> deleteNode(Integer departmentid) {
Map<String, Object> resultMap = new HashMap<>();
departmentDao.deleteById(departmentid);
resultMap.put("success", true);
return resultMap;
}
}
7、编写前端代码
HTML页面:department.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试Tree功能</title>
<link rel="stylesheet" type="text/css" href="../easyui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="../easyui/themes/icon.css">
<script type="text/javascript" src="../easyui/jquery.min.js"></script>
<script type="text/javascript" src="../easyui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="../easyui/locale/easyui-lang-zh_CN.js"></script>
<script type="text/javascript" src="../biz/department.js"></script>
</head>
<body>
<!-- 部门树 -->
<ul id="deptTree" class="easyui-tree"></ul>
<!-- 叶子节点右键菜单 -->
<div id="leaf" class="easyui-menu" style="width: 120px;">
<div onclick="addNode()" iconcls="icon-add">新增节点</div>
<div onclick="removeNode()" iconcls="icon-remove">删除节点</div>
<div onclick="updateNode()" iconcls="icon-edit">编辑节点</div>
</div>
<!-- 非叶子节点右键菜单 -->
<div id="parentNode" class="easyui-menu" style="width: 120px;">
<div onclick="addNode()" iconcls="icon-add">新增节点</div>
<div onclick="updateNode()" iconcls="icon-edit">编辑节点</div>
</div>
<!-- 节点内容对话框 -->
<div id="info" class="easyui-dialog" style="width:300px; height: 120px;" closed=true>
<form id="treefrm" method="post">
<input type="hidden" name="departmentid">
<table style="margin: auto;" cellspacing="10">
<tr>
<td>部门名称</td>
<td><input class="easyui-textbox" name="departmentname" value="" data-options="required:true"></td>
</tr>
</table>
<div style="text-align: center; bottom: 15px; margin-top: 10px;">
<a id="btnSave" class="easyui-linkbutton"
data-options="iconCls:'icon-save'">保存</a>
<a id="btnCancel" class="easyui-linkbutton"
data-options="iconCls:'icon-cancel'">取消</a>
</div>
</form>
</div>
</body>
</html>
对应JS文件:department.js
// 记录添加还是修改
var flag;
// 临时存储选中节点数据
var tempNode; // 页面加载
$(function () {
// 菜单树绑定数据
$('#deptTree').tree({
url: '/department/tree',
animate: true,
lines: true,
onBeforeSelect: function (node) {
// onBeforeSelect事件:节点被选中前触发,返回false则取消选择动作
if (!$(this).tree('isLeaf', node.target)) {
// 不是叶子节点,则不能选中
return false;
}
},
onClick: function (node) {
// alert(node.target.innerText);
},
onContextMenu: function (e, node) {
// 记录选中的节点,为后续增删改操作提供节点数据
tempNode = node; // 阻止右键默认事件
e.preventDefault(); // 判断该结点有没有父结点
var root = $(this).tree('getParent', node.target);
// 没有父节点则为根结点,可以新增、编辑,不可以删除
if (root == null) {
// 如果是根节点,则可以新增、编辑,不可以删除
$('#parentNode').menu('show', {
left: e.pageX,
top: e.pageY
});
} if ($(this).tree('isLeaf', node.target)) {
// 如果是叶子节点,则可以新增、编辑和删除
$('#leaf').menu('show', {
left: e.pageX,
top: e.pageY
});
} else {
// 如果不是叶子节点,则可以新增、编辑,不可以删除
$('#parentNode').menu('show', {
left: e.pageX,
top: e.pageY
});
}
}
}); // 保存按钮押下处理
$('#btnSave').click(function () {
var tempdata, tempurl, tempmsg; if (flag == 'add') {
tempurl = 'saveNode';
tempmsg = '添加成功!';
tempdata = {
departmentpid: tempNode.id,
departmentname: $('#treefrm').find('input[name=departmentname]').val()
};
} else if (flag == 'edit') {
tempurl = 'updateNode';
tempmsg = '编辑成功!';
tempdata = {
departmentid: $('#treefrm').find('input[name=departmentid]').val(),
departmentpid: $('#deptTree').tree('getParent', tempNode.target).id,
departmentname: $('#treefrm').find('input[name=departmentname]').val()
};
} $.ajax({
type: 'post',
async: true,
url: tempurl,
data: tempdata,
dataType: 'json',
success: function (result) {
// 树重新加载
$('#deptTree').tree('reload'); $.messager.show({
title: '提示信息',
msg: tempmsg
});
},
error: function (result) {
// 请求失败时执行该函数
$.messager.show({
title: '错误信息',
msg: result.msg
});
}
}); $('#treefrm').form('clear');
$('#info').dialog('close');
}); // 取消按钮押下处理
$('#btnCancel').click(function () {
$('#treefrm').form('clear');
$('#info').dialog('close');
});
}); // 新增节点
var addNode = function () {
flag = 'add';
// 清空表单数据
$('#treefrm').form('clear');
// 打开dialog
$('#info').dialog('open').dialog('setTitle', '新增');
}; // 编辑节点
var updateNode = function () {
flag = 'edit';
// 清空表单数据
$('#treefrm').form('clear');
$('#treefrm').form('load', {
departmentid: tempNode.id,
departmentname: tempNode.text
});
// 打开dialog
$('#info').dialog('open').dialog('setTitle', '编辑');
}; // 删除节点
var removeNode = function () {
// 前台删除
$('#deptTree').tree('remove', tempNode.target); // 后台删除
$.ajax({
type: "post",
async: true, // 异步请求(同步请求将会锁住浏览器,用户其他操作必须等待请求完成才可以执行)
url: "deleteNode",
data: {departmentid: tempNode.id},
dataType: "json", // 返回数据形式为json
success: function (result) {
// 请求成功时执行该函数内容,result即为服务器返回的json对象
$.messager.show({
title: '提示信息',
msg: '删除成功!'
});
},
error: function (result) {
// 请求失败时执行该函数
$.messager.show({
title: '错误信息',
msg: result.msg
});
}
});
};
8、运行效果
【原】无脑操作:EasyUI Tree实现左键只选择叶子节点、右键浮动菜单实现增删改的更多相关文章
- EasyUI Combotree只选择叶子节点
EasyUI Combotree的方法拓展自Combo和Tree.而Tree有一个onBeforSelect事件来帮助我们实现只选择叶子节点的功能. Tree事件需要 'node' 参数,它包括下列属 ...
- 【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础授权权限
上一篇<[原]无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限>介绍了实现Shiro的基础认证.本篇谈谈实现 ...
- 【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限
开发环境搭建参见<[原]无脑操作:IDEA + maven + SpringBoot + JPA + Thymeleaf实现CRUD及分页> 需求: ① 除了登录页面,在地址栏直接访问其他 ...
- 【原】无脑操作:express + MySQL 实现CRUD
基于node.js的web开发框架express简单方便,很多项目中都在使用.这里结合MySQL数据库,实现最简单的CRUD操作. 开发环境: IDE:WebStorm DB:MySQL ------ ...
- Jquery EasyUI Combotree只能选择叶子节点且叶子节点有多选框
Jquery EasyUI Combotree只能选择叶子节点且叶子节点有多选框 Jquery EasyUI Combotree单选框,Jquery EasyUI Combotree只能选择叶子节点 ...
- 【原】无脑操作:eclipse + maven搭建SSM框架
网上看到一些Spring + Spring MVC + MyBatis框架的搭建教程,不是很详细或是时间久远了,自己动手整一个简单无脑的! 0.系统环境 1)Windows 10 企业版 2)JDK ...
- 【原】无脑操作:ElasticSearch学习笔记(01)
开篇来自于经典的“保安的哲学三问”(你是谁,在哪儿,要干嘛) 问题一.ElasticSearch是什么?有什么用处? 答:截至2018年12月28日,从ElasticSearch官网(https:// ...
- easyui Tree模拟级联勾选cascadeCheck,节点选择,父节点自动选中,节点取消,父节点自动取消选择,节点选择,所有子节点全部选择,节点取消,所有子节点全部取消勾选
最近项目中用到easyui tree,发现tree控件的cascadeCheck有些坑,不像miniui 的tree控件,级联勾选符合业务需求,所以就自己重新改写了onCheck事件,符合业务需求.网 ...
- EasyUI Combotree 只允许选择 叶子节点
$("#SDID").combotree({ url: '/Ajax/GetDeptTree.aspx?level=4&pid=-1', onSelect: functio ...
随机推荐
- 如何在新工程中添加两个不同版本的的echarts库
emmmmm.....标题我就觉得起的很变态.闲话不多说,先说出现的背景吧--. 因为业务上的需求,跟一个硬件对接,要做大屏展示大厅客流热力图分布(背景图是客户那边给的).然后这个机子传过来的数据就可 ...
- cesium 之地图贴地量算工具效果篇(附源码下载)
前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材. 内 ...
- Oracle数据库升级注意事项
1 备份配置参数 数据库升级前的配置参数要备份,如PGA大小 这样数据库升级后还可以升级前的配置,而不至于使用安装升级时的默认配置 2 检查版本兼容 确认数据库升级后是否对生产环境上的代码有影响,如果 ...
- 通过href链接实现从当前页面跳转到动态页的指定页面的实现方式
指定页的jsp的href设置 <a href="/lekg/check/shangchuan2.jsp?tabtype=2"><li><img src ...
- Spring boot 配置文件详解 (properties 和yml )
从其他框架来看 我们都有自己的配置文件, hibernate有hbm,mybatis 有properties, 同样, Spring boot 也有全局配置文件. Springboot使用一个全局的配 ...
- Win7系统修改hosts无法保存怎么办?
背景 有的时候我们需要修改hosts文件,但是在某些情况下竟提示保存不了.之前有一次IntelliJ IDEA提示我快到期了,于是我到网上找到了一个激活方法,但需要将一个地址放到hosts文件中去,此 ...
- SVN的安装与配置
单独安装 SVN:1.安装:yum -y install subversionmkdir -p /data/svn/ 创建创库目录svnadmin create /data/svn/repos 构建版 ...
- Java遍历List集合的4种方式
public class Test { public static void main(String[] args) { // 循环遍历List的4中方法 List<String> str ...
- 重新发现MATLAB
现场编辑 创建不仅捕获代码的脚本 - 它们讲述了可以与他人共享的故事.自动化的上下文提示可让您在编程时快速移动,并将结果和可视化与代码一起显示. 学到更多 访问MATLAB实时脚本库 ...
- 理解ASP.NET Core验证模型(Claim, ClaimsIdentity, ClaimsPrincipal)不得不读的英文博文
这篇英文博文是 Andrew Lock 写的 Introduction to Authentication with ASP.NET Core . 以下是简单的阅读笔记: -------------- ...