實戰:使用jqGrid實現非同步樹形列表
阿新 • • 發佈:2018-11-13
今天教大家使用jqGrid來實現非同步載入的樹形列表
先上效果圖:
非同步載入即不一次性的將所有的資料載入到頁面上,只有當需要的時候點選三角按鈕,才會將其子類載入到頁面上顯示,若其下無子類,則是圓圈標識。
下面是實現的步驟:
1.下載並引用必要的檔案
這個就不詳細講了,網上有許多教程。
2.前端頁面
一個table
一段JS
var jqGrid; $(function() { var width = $(".lz-card-body").width() - 20; jqGrid = jQuery('#tree').jqGrid({ // "url" : "/IssueConfig/findByPIdAndLevel", "datatype" : "json", "colModel" : [ { "name" : "issConfigId", "index" : "issConfigId", "sorttype" : "int", "key" : true, "hidden" : true }, { "name" : "descCn", "label" : "中文名稱", "sortable" : false, /* formatter : function(cellvalue, options, rowObject) { var viewUrl = "/sysMenu/toView/" + rowObject.id; var html = "<a href='" + viewUrl; html += "' target=_blank>"; html += cellvalue; html += "</a>"; return html; } */ }, { "name" : "descEn", "label" : "英文名稱", "sortable" : false }, { "name" : "issCode", "label" : "序號", "sortable" : false, "align" : "center" }, { "name" : "issHelp", "label" : "問題幫助", "sortable" : false, "align" : "center" }, { "name" : "sort", "label" : "排序", "sortable" : false, "align" : "center", /* formatter : function(cellvalue, options, rowObject) { if(cellvalue){ return cellvalue.labelCn; } return ''; } */ }, { "name" : "operation", "label" : "操作", "sortable" : false, "width" : 100, "align" : "center", formatter : function(cellvalue, options, rowObject) { var id = rowObject.issConfigId; var addUrl = "/IssueConfig/toAdd/" + id; var editUrl = "/IssueConfig/toEdit/" + id; var html = "<a href='" + addUrl; html += "' target=_blank title='add'>"; html += "<i class='fa fa-plus'></i></a> "; html += "<a href='" + editUrl; html += "' target=_blank title='edit'>"; html += "<i class='far fa-edit'></i></a>"; html += " <a href='#' title='delete' onclick=deleteMenu("; html += id; html += ")><i class='fa fa-trash'></i></a>"; return html; } }, { "name" : "parentId", "hidden" : true }, { "name" : "level", "hidden" : true }, { "name" : "isLeaf", "hidden" : true }, { "name" : "expanded", "hidden" : true }, { "name" : "loaded", "hidden" : true } ], "width" : width, "hoverrows" : false, "viewrecords" : false, "gridview" : true, "height" : "auto", "sortname" : "issConfigId", "sortable" : false, "scrollrows" : true, "tree_root_level" : 0, "treeGrid" : true, "ExpandColumn" : "descCn", "treedatatype" : "json", "treeGridModel" : "adjacency", "loadonce" : false, "rowNum" : 100, "treeReader" : { "parent_id_field" : "parentId", "level_field" : "level", "leaf_field" : "isLeaf", "expanded_field" : "expanded", "loaded" : "loaded", "icon_field" : "icon1" } }); });
哎.....寫的草稿沒儲存,不想在寫一遍了
說一下重要的引數吧
tree_root_level" : 0,
"treeGrid" : true,
"ExpandColumn" : "descCn",
"treedatatype" : "json",
"treeGridModel" : "adjacency",
"loadonce" : false,
下面的是詳細的api文件,不是太難
https://blog.csdn.net/yjlwl1213/article/details/41750703
3.後臺程式碼
首先要知道,因為是弄清楚前臺需要給後臺什麼引數,後臺返給前臺的資料結構是什麼樣子。
1.前臺給後臺
因為是非同步載入,點選父節點才加載出其直接子節點,那麼肯定要發回parent id,然後每一層 它的Level都要加1,所以要把父節點的level發回。
/** * 根據parent_id和level查詢選單(非同步載入) * * @param parentId * @param level * @return */ @RequestMapping(value = "/findByPIdAndLevel", method = RequestMethod.GET) @ResponseBody public List<IssueConfigVo> findByPIdAndLevel() { //獲得父節點和父節點的level String nodeId = request.getParameter("nodeid"); String n_level = request.getParameter("n_level"); //null的話即為最開始載入的level=0的根節點 Long parentId = StringUtils.isEmpty(nodeId) ? null : Long.parseLong(nodeId); Integer level = StringUtils.isEmpty(n_level) ? null : Integer.parseInt(n_level); return issueConfigService.getMenusTree(parentId, level); }
2.搞清楚要返回的資料結構,怎麼樣才能被前臺識別形成樹結構
//返回的類
public class IssueConfigVo extends IssueConfig {
private static final long serialVersionUID = 1L;
private Long id;
//父節點 id 其實這邊不需要也可以,因為基礎類裡面就已經有parent 欄位了,只需要在Js中設定一下
private Long parent;
private Integer level = 0;
private boolean isLeaf;
private boolean loaded = false;
private boolean expanded = true;
//資料
private IssueConfig father;
}
//實體類
@Entity
@Table(name = "NT_T_ISSUE_CONFIG")
public class IssueConfig extends BaseEntity {
private static final long serialVersionUID = 1L;
// 主鍵
private Long issConfigId;
// 建立時間
private Date createDate;
// 建立人ID
private String createUserid;
// 建立人
private String createUsername;
// 中文描述
private String descCn;
// 英文描述
private String descEn;
// 問題序號
private String issCode;
// 問題幫助
private String issHelp;
// 修改時間
private Date modifyDate;
// 修改人員ID
private String modifyUserid;
// 上次節點
private Long parentId;
// 問題排序
private Integer sort;
// 狀態
private String status;
}
3.遞迴獲取List
/**
* 遞迴選單
*
* @param param
* @return
*/
public List<IssueConfigVo> getMenusTree(Long pid, Integer level) {
List<IssueConfigVo> issueConfigVoList = new ArrayList<IssueConfigVo>();
//根據父節點id,找到其直接子節點
List<IssueConfigVo> issueConfigVo = IssueConfigVo
.setList(findByParentId(pid));
//設定level,因為我這邊的業務需求,只有兩層,如果需要多層,使用level +=1遞增
if (level == null) {
level = 0;
} else {
level = 1;
}
if (issueConfigVo != null && !issueConfigVo.isEmpty()) {
for (IssueConfigVo menuVo : issueConfigVo) {
//設定子節點屬性
menuVo.setLevel(level);
//這邊是因為剛寫的時候不瞭解,遞迴獲取了子節點,其實是不需要的,
//因為實體類中有parent欄位,我們只需要設定好parentId,並在前端
//js裡面設定好,jqgrid就能將樹拼接好
/*List<IssueConfigVo> children = getMenusTree(menuVo
.getIssConfigId());*/
if (children.isEmpty()) {
menuVo.setIsLeaf(true);
} else {
menuVo.setIsLeaf(false);
}
// menuVo.setChildren(children);
//設定parentId,一定要設定
menuVo.setParent(menuVo.getParentId());
issueConfigVoList.add(menuVo);
}
}
return issueConfigVoList;
}
//下面是遞迴獲取子節點,有興趣的人可以看一下,其實不需要
/**
* 遞迴選單
*
* @param param
* @return
*/
public List<IssueConfigVo> getMenusTree(Long pid) {
List<IssueConfigVo> issueConfigVoList = new ArrayList<IssueConfigVo>();
List<IssueConfigVo> issueConfigVo = IssueConfigVo
.setList(findByParentId(pid));
if (issueConfigVo != null && !issueConfigVo.isEmpty()) {
for (IssueConfigVo menuVo : issueConfigVo) {
menuVo.setChildren(getMenusTree(menuVo.getIssConfigId()));
issueConfigVoList.add(menuVo);
}
}
return issueConfigVoList;
}
然後樹就完成啦!最後,其實js裡面也不需要那麼麻煩,因為也是第一次寫所以不熟悉,下面是精簡班,主要功能不變,後臺程式碼也不需要變動
jQuery(grid_selector).jqGrid({
treeGrid : true,
width : width,
treeGridModel : "adjacency",
ExpandColumn : "descCn",
ExpandColClick : false,
url : "/IssueConfig/findByPIdAndLevel",
datatype : "json",
colModel : [ {
name : "issConfigId",
index : "issConfigId",
key : true,
hidden : true,
formatter : function(cellvalue, options, rowObject) {
var rowId = rowObject.issConfigId;
var checkbox = '<input type="hidden" name=""';
checkbox += 'value="';
checkbox += rowId
checkbox += '"/>';
return checkbox;
}
}, {
label : nameFormat,
name : "descCn",
index : "descCn",
formatter : function(cellvalue, options, rowObject) {
index++;
var rowId = rowObject.issConfigId;
var descCn = rowObject.descCn;
var checkbox = '<input type="checkbox" id="chx';
checkbox += rowId;
checkbox += '" value="';
checkbox += descCn;
checkbox += '" onclick="clickCheckbox(';
checkbox += rowId;
checkbox += ', this);"';
checkbox += 'name=""';
checkbox += ' />';
checkbox += rowObject.descCn;
return checkbox;
}
}, {
label : "英文名稱",
name : "descEn",
index : "descEn",
formatter : function(cellvalue, options, rowObject) {
var descEn = rowObject.descEn;
var checkbox = '<input type="hidden" ';
checkbox += ' name="" value="';
checkbox += descEn;
checkbox += '"/>';
checkbox += rowObject.descEn;
return checkbox;
}
} ,{
name : "issCode",
hidden : true,
formatter : function(cellvalue, options, rowObject) {
var issCode = rowObject.issCode;
var checkbox = '<input type="hidden" name=""';
checkbox += 'value="';
checkbox += issCode
checkbox += '"/>';
return checkbox;
}
}, {
name : "sort",
hidden : true,
formatter : function(cellvalue, options, rowObject) {
var sort = rowObject.sort;
var checkbox = '<input type="hidden" name=""';
checkbox += 'value="';
checkbox += sort
checkbox += '"/>';
return checkbox;
}
},{
name : "parentId",
hidden : true,
formatter : function(cellvalue, options, rowObject) {
var parentId = rowObject.parentId;
var checkbox = '<input type="hidden" name=""';
checkbox += 'value="';
checkbox += parentId
checkbox += '"/>';
return checkbox;
}
} ],
page : false,
rowNum: 100,
loadonce : false,
tree_root_level : 0,
gridview : true,
height : "auto"
});
有問題可以交流