樹形結構在實際開發中是很長用的一種結構。最近寫了一個LayUI的小案例,其中用到了TreeSelect,這裏整理一下。
TreeSelect官網地址:https://fly.layui.com/extend/treeSelect/
顯示效果圖。
因爲TreeSelect不是LayUI官方開發的,而是第三方基於LayUI開發的,所以需要先用Layui引入一下文件。
之後頁面只需要引入LayUI的CSS和JS就可以了。
頁面給一個標籤,用於顯示TreeSelect下拉樹選中的內容值,獲取選中值時,直接獲取標籤值,就是選中的內容值。
<input type="text" name="parentId" id="tree2" lay-filter="tree2" class="layui-input" />
JS渲染樣式代碼。
<script type="text/javascript">
layui.use(["treeSelect", "form", "tree"], function () {
var form = layui.form;
var tree = layui.tree;
var treeSelect = layui.treeSelect;
treeSelect.render({
// 選擇器
elem: '#tree',
// 異步獲取下拉樹需要顯示的數據
data: 'dept/treeSelect',
// 異步加載方式:get/post,默認get
type: 'post',
// 佔位符
placeholder: '上級菜單',
// 是否開啓搜索功能:true/false,默認false
search: true,
// 一些可定製的樣式
style: {
folder: {
enable: true
},
line: {
enable: true
}
},
// 點擊節點回調
click: function(d){
//console.log(d);
},
// 加載完成後的回調函數
success: function (d) {
//console.log(d);
// 選中節點,根據id篩選,一般修改時會有默認選中狀態,可以在這裏設置
//treeSelect.checkNode('tree', 2);
//console.log($('#tree').val());
// 獲取zTree對象,可以調用zTree方法
//var treeObj = treeSelect.zTree('tree');
// console.log(treeObj);
// 刷新樹結構
//treeSelect.refresh('tree');
}
});
});
</script>
後臺響應加載下拉樹數據方法(有詳細註釋)。
@RequestMapping(value="/treeSelect")
@ResponseBody
//這裏寫的,新增和修改數據請求都是同一個方法,如果是修改會傳遞一個修改對象的id
public Object treeSelect(Integer id) {
Sort sort = Sort.by("idx"); //排序
Specification<Dept> spec = buildSpec1(); //查詢條件,查詢父節點爲null的元素
List<Dept> list = deptService.findAll(spec,sort); //查詢,Dept爲實體類
return buildTree(list, id); //轉換爲treeSelect指定的JSON數據格式方法
}
private Object buildTree(List<Dept> list, Integer id) {
List<HashMap<String, Object>> result=new ArrayList<>();
for (Dept dept : list) {
if(dept.getId() != id) { //判斷如果是修改的話,修改的節點及下級節點不顯示,也就不加載
HashMap<String, Object> node=new HashMap<>();
node.put("id", dept.getId()); //節點id
node.put("name",dept.getName()); //節點數據名稱
node.put("open", false); //是否展開
node.put("checked", false); //是否選中,前臺也可以設置是否選中
if(dept.getChildren().size() != 0) { //如果下級節點不爲空,
node.put("children",buildTree(dept.getChildren(), id)); //遞歸加載下級節點
}
result.add(node);
}
}
return result;
}
public Specification<Dept> buildSpec1() {
Specification<Dept> specification = new Specification<Dept>() {
private static final long serialVersionUID = 1L;
@Override
public Predicate toPredicate(Root<Dept> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
HashSet<Predicate> rules=new HashSet<>();
Predicate parent = cb.isNull(root.get("parent")); //查詢父節點爲null的元素
rules.add(parent);
return cb.and(rules.toArray(new Predicate[rules.size()]));
}
};
return specification;
}
Dept實體類代碼。
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.data.annotation.CreatedBy;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
public class Dept {
private Integer id;
private String name; //部門名稱
private String deptName; //部門負責人
private String phone; //電話號
private String number; //編號
private double idx; //排序
@JsonIgnore
private Dept parent;
@JsonIgnore
private List<Dept> children = new ArrayList<>();
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public double getIdx() {
return idx;
}
public void setIdx(double idx) {
this.idx = idx;
}
@ManyToOne
@CreatedBy
public Dept getParent() {
return parent;
}
public void setParent(Dept parent) {
this.parent = parent;
}
@OneToMany(cascade=CascadeType.ALL,mappedBy="parent")
@OrderBy(value="idx")
public List<Dept> getChildren() {
return children;
}
public void setChildren(List<Dept> children) {
this.children = children;
}
public Dept(Integer id, String name, String deptName, String phone, String number, double idx, Dept parent, List<Dept> children) {
this.id = id;
this.name = name;
this.deptName = deptName;
this.phone = phone;
this.number = number;
this.idx = idx;
this.parent = parent;
this.children = children;
}
public Dept(Integer id) {
this.id = id;
}
public Dept() {
}
}
這裏後臺持久層是使用的Spring-Data-Jpa,如果你是用的其他持久層框架,只要返回的JSON數據格式一樣就可以了。
JSON數據格式。
JSON數據。
[
{
"children": [ //下級節點
{
"children": [
{
"name": "測試",
"checked": false,
"id": 30,
"open": false
}, {
"name": "開發",
"checked": false,
"id": 31,
"open": false
}, {
"children": [
{
"name": "測試節點",
"checked": false,
"id": 36,
"open": false
}
],
"name": "測試",
"checked": false,
"id": 32,
"open": false
}
],
"name": "技術部",
"checked": false,
"id": 2,
"open": false
}, {
"name": "財務部",
"checked": false,
"id": 19,
"open": false
}
],
"name": "某某公司", //節點內容
"checked": false, //是否選中
"id": 1, //id
"open": false //是否展開
}, {
"name": "測試",
"checked": false,
"id": 33,
"open": false
}
]