我们创建了一个代表文件系统的jqGrid TreeGrid,其中分支是文件夹,叶子是文件。我们已经在TreeGrid中实现了一些功能,通过使用addChildNode
来创建新的“文件”。但是,我们还想添加创建新文件夹的功能。我们的脚本可以创建新的文件夹,但它们不会立即显示在TreeGrid上,除非它或页面被重新加载。但是,重新加载TreeGrid会折叠所有文件夹,这特别令人讨厌。
有没有办法有选择地刷新TreeGrid的节点,或添加一个功能正常的新分支?我在addJSONData
上看到了一些部分文档,但使用此函数会彻底清除TreeGrid直到刷新。我还试图使用addChildNode
并更改某些属性,我尝试使用DOM操作手动添加行;但是,这两种方法都会破坏插入的节点。
编辑:
var grid = $("#grid");
grid.jqGrid({
treeGrid: true,
treeGridModel: "adjacency",
ExpandColumn: 'name',
ExpandColClick: true,
url:"",
datatype:"json",
colNames:['id','Name','Authorization','Views','Uri'],
colModel:[ {name:'id', index:'id', hidden:true, key:true},
{name:'name', index:'name', sorttype:"text", width:3, sortable:false},
{name:'auth',index:'auth', sorttype:"text", sortable:false, hidden:true},
{name:'views',index:'views', sorttype:"integer", width:1, sortable:false, align:"center"},
{name:'uri',index:'uri',sorttype:'text',sortable:false,hidden:true}],
jsonReader:{ root:"rows"
,page:"page"
,total:"total"
,records:"records"
,repeatitems:false
,cell:""
,id:"0"
,userdata:""
},
multiselect:false,
autowidth:true,
height:"auto",
sortable:false,
toppager:true,
hidegrid: false,
loadui: 'block',
pager:"#grid_pager",
caption: "Files",
});
新文件夹返回的JSON请求如下所示:
ret = {"error":"","total":1,"page":1,"records":1,"rows":[{"id":"1113","name":"test","uri":"accounting\/test\/","parent":1,"isLeaf":false,"expanded":true,"loaded":true}]}
我尝试使用以下内容添加:
grid[0].addJSONData(ret);
加载的初始数据以JSON:
发送{"rows":[
{"id":"1","uri":"afolder\/","parent_id":"0","name":"afolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"4","uri":"bfolder\/","parent_id":"0","name":"bfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"7","uri":"cfolder\/","parent_id":"0","name":"cfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"20","uri":"dfolder\/","parent_id":"0","name":"dfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"48","uri":"efolder\/","parent_id":"0","name":"efolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"179","uri":"ffolder\/","parent_id":"0","name":"ffolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"182","uri":"gfolder\/","parent_id":"0","name":"gfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"186","uri":"hfolder\/","parent_id":"0","name":"hfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"201","uri":"ifolder\/","parent_id":"0","name":"ifolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"239","uri":"jfolder\/","parent_id":"0","name":"jfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"253","uri":"kfolder\/","parent_id":"0","name":"kfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"262","uri":"lfolder\/","parent_id":"0","name":"lfolder","level":0,"parent":"0","isLeaf":"false"},
{"id":"274","uri":"mfolder\/","parent_id":"0","name":"mfolder","level":0,"parent":"0","isLeaf":"false"}
]}
答案 0 :(得分:2)
The demo显示了如何使用addChildNode方法添加树节点。我添加了您发布"loaded":true
部分的JSON数据,因为我在测试中没有使用服务器组件,我想立即加载treegrid。
为了表明你应该非常小心新添加的行的ID我在演示中添加了两个按钮:“插入树节点”和“插入带有唯一rowid的树节点”。第一个按钮使用您发布的数据中的id =“1113”。单击按钮工作正确。第二次单击将插入具有id重复项的行,这将是一个错误。您可以在不同的Web浏览器中看到不同的错误。第二个按钮使用$.jgrid.randId()
生成唯一的rowid。它可能不是您的方案中的一个选项,但它适用于本地树网格(如我的演示中)。
另一个问题是您在演示中使用“父”:“0”表示根元素。正确的将是"parent":null
或"parent":"null"
(请参阅the answer)。此外,名称为"parent_id"
的属性将被忽略。我从演示中删除了一些设置,以便可以在treegrid中使用本地排序。
答案 1 :(得分:1)
我们通过扩展jqGrid源的功能解决了这个问题。首先,我们创建了一个可以删除特定文件夹(文件夹/分支和文件/叶子)的所有子节点的函数,以便我们可以重新加载它们,从而获得最新的子集。此函数采用整数rowid
,就像delTreeNode()
。
delChildren : function (rowid) {
return this.each(function () {
var $t = this, rid = $t.p.localReader.id,
left = $t.p.treeReader.left_field,
right = $t.p.treeReader.right_field, myright, width, res, key;
if(!$t.grid || !$t.p.treeGrid) {return;}
var rc = $t.p._index[rowid];
if (rc !== undefined) {
// nested
myright = parseInt($t.p.data[rc][right],10);
width = myright - parseInt($t.p.data[rc][left],10) + 1;
var dr = $($t).jqGrid("getFullTreeNode",$t.p.data[rc]);
if(dr.length>0){
for (var i=0;i<dr.length;i++){
if(dr[i][rid] != rowid)
$($t).jqGrid("delRowData",dr[i][rid]);
}
}
if( $t.p.treeGridModel === "nested") {
// ToDo - update grid data
res = $.jgrid.from($t.p.data)
.greater(left,myright,{stype:'integer'})
.select();
if(res.length) {
for( key in res) {
res[key][left] = parseInt(res[key][left],10) - width ;
}
}
res = $.jgrid.from($t.p.data)
.greater(right,myright,{stype:'integer'})
.select();
if(res.length) {
for( key in res) {
res[key][right] = parseInt(res[key][right],10) - width ;
}
}
}
}
});
},
然后,我们创建了一个强制重新加载某个节点(文件夹)的函数。
reloadNode: function(rc) {
return this.each(function(){
if(!this.grid || !this.p.treeGrid) {return;}
var rid = this.p.localReader.id;
$(this).jqGrid("delChildren", rc[rid]);
var expanded = this.p.treeReader.expanded_field,
parent = this.p.treeReader.parent_id_field,
loaded = this.p.treeReader.loaded,
level = this.p.treeReader.level_field,
lft = this.p.treeReader.left_field,
rgt = this.p.treeReader.right_field;
var id = $.jgrid.getAccessor(rc,this.p.localReader.id);
var rc1 = $("#"+id,this.grid.bDiv)[0];
rc[expanded] = true;
$("div.treeclick",rc1).removeClass(this.p.treeIcons.plus+" tree-plus").addClass(this.p.treeIcons.minus+" tree-minus");
this.p.treeANode = rc1.rowIndex;
this.p.datatype = this.p.treedatatype;
if(this.p.treeGridModel == 'nested') {
$(this).jqGrid("setGridParam",{postData:{nodeid:id,n_left:rc[lft],n_right:rc[rgt],n_level:rc[level]}});
} else {
$(this).jqGrid("setGridParam",{postData:{nodeid:id,parentid:rc[parent],n_level:rc[level]}} );
}
$(this).trigger("reloadGrid");
rc[loaded] = true;
if(this.p.treeGridModel == 'nested') {
$(this).jqGrid("setGridParam",{postData:{nodeid:'',n_left:'',n_right:'',n_level:''}});
} else {
$(this).jqGrid("setGridParam",{postData:{nodeid:'',parentid:'',n_level:''}});
}
});
},
这与expandNode()
相同,但不会检查节点是否已扩展为开头,并强制它为该节点的子元素发送AJAX请求。这样,我们总是有最新的孩子。
最后,我们修复了getRowData()
中的一个小错误,它阻止我们使用它向record
或我们新创建的expandNode()
提供reloadNode()
参数。问题是JSON返回中的_id_
字段从未创建或填充过。添加固定的expandNode()
和reloadNode()
以下是更改的来源。不理想,但它有效。
getRowData : function( rowid ) {
var res = {}, resall, getall=false, len, j=0;
this.each(function(){
var $t = this,nm,ind;
if(typeof(rowid) == 'undefined') {
getall = true;
resall = [];
len = $t.rows.length;
} else {
ind = $t.rows.namedItem(rowid);
if(!ind) { return res; }
len = 2;
}
while(j<len){
if(getall) { ind = $t.rows[j]; }
if( $(ind).hasClass('jqgrow') ) {
$('td',ind).each( function(i) {
nm = $t.p.colModel[i].name;
if ( nm !== 'cb' && nm !== 'subgrid' && nm !== 'rn') {
if($t.p.treeGrid===true && nm == $t.p.ExpandColumn) {
res[nm] = $.jgrid.htmlDecode($("span:first",this).html());
} else {
if($t.p.colModel[i].key != undefined && $t.p.colModel[i].key == true)
{
try {
res["_" + nm + "_"] = $.unformat(this,{rowId:ind.id, colModel:$t.p.colModel[i]},i);
} catch (e){
res["_" + nm + "_"] = $.jgrid.htmlDecode($(this).html());
}
}
try {
res[nm] = $.unformat(this,{rowId:ind.id, colModel:$t.p.colModel[i]},i);
} catch (e){
res[nm] = $.jgrid.htmlDecode($(this).html());
}
}
}
});
if(getall) { resall.push(res); res={}; }
}
j++;
}
});
return resall ? resall: res;
},
最后,我们将这一切全部拉到一起,使用JSON返回对象来创建文件夹,例如
{{"id":"1267", "name":"test15", "uri":"sample1\/test15\/", "parent_id":1, "parent":1, "isLeaf":false}
我们称这个函数为
var parentid = ret.rows[0].parent;
var parent = grid.jqGrid('getRowData', parentid);
grid.jqGrid('reloadNode', parent);
这些函数将删除parent的所有子节点,然后从数据库发送新的更新列表的AJAX请求。如果可能的话,我将把它推到jqGrid Github上,因为reload
函数可能对许多人有用。我已将其发布在此处,以防它未获批准。