jqGrid - 新行的唯一 ID
jqGrid - Unique ID for new row
我正在尝试为添加到我的 jqGrid 中的新行分配一个唯一 ID。我使用免费的 jqGrid 4.11.0,服务器端的 java 休息服务和数据库的 MS SQL。
inlineEditing: {
ajaxSaveOptions: { contentType: "application/json" },
serializeSaveData: function (postData) {
var idArray = grid.getCol('id');
var count = 0;
var k = 1;
while(postData.id.search('jqg') != '-1'){
for(var i =0 ; i<idArray.length;i++){
if(k == idArray[i]){
count++;
}
if(count == 0){
postData.id = k ;
break;
}
}
k++;
}
return JSON.stringify(postData);
}
}
我注意到 jqGrid 给出的默认 ID 是 jqg + 一个数字。关于如何制作当前未在任何数据库记录上使用的唯一 ID 的任何建议?我应该从服务器端执行此操作还是可以在 jqGrid 代码中执行此操作?
在晚上的某个时候,这段代码有点工作,并继续为所有新行提供 id 7 [即使它应该继续增加]。经过一些更改[不记得有什么更改],每次我单击保存将新行提交到服务器时,页面冻结并且 chrome 建议我应该终止进程。
请让我知道什么以及是否应该添加更多信息。
编辑 1:
$(function () {
var grid = $('#grid'),
checkboxEditOptionEvents = [
{type : 'click', data: {'Yes': 'Yes'}, fn: function (e, id) {
var checkboxCol = grid.getCol('sefDepartament'),
ids = grid.jqGrid('getDataIDs'),
numberOfCheckedBoxes = [],
k;
for (k = 0; k < ids.length; k++) {
if(checkboxCol[k] == 'Yes'){
numberOfCheckedBoxes.push(checkboxCol[k]);
if (numberOfCheckedBoxes.length == 1){
alert('Please deselect the other checked box first');
$(this).prop("checked",false);
numberOfCheckedBoxes = 0;
}
}
}
}}];
var experienceFunction = function(cellvalue, options ,rowObject){
var joinYearVar = rowObject.joinYear,
YY = joinYearVar.slice(0,4),
MM = joinYearVar.slice(5,7),
DD= joinYearVar.slice(8,11);
return moment("\"" +YY+MM+DD+"\"" , "YYYYMMDD").fromNow();
};
var checkboxFormatFunc = function(cellvalue, options ,rowObject){
if(cellvalue == 'Yes'){
return 'Yes';
}
return 'No';
};
var afterSaveFunction = function(id){
var prenumeVar = grid.getCell(id, 'prenume').trim(),
numeVar = grid.getCell(id,'nume').trim(),
usernameVar = numeVar +'.'+ prenumeVar,
emailVar = usernameVar + '@test.com';
usernameVar =usernameVar.replace(/\s/g , '').trim();
emailVar = emailVar.replace(/\s/g , '');
grid.setCell(id, 'username', usernameVar);
grid.setCell(id, 'email', emailVar);
};
var colModelSettings = [
{name:'id', label:'id',key: true,hidden: true, width:10,sorttype:'number',editable: false},
{name:'nume',label:'Nume',width:90, align: 'center',editable:true,searchoptions: {sopt: ['eq','bw','ew','cn']}, editrules:{required:true}, editoptions: {defaultValue: ' '},formatter: 'text'},
{name:'prenume',label:'Prenume',width:100,editable:true,searchoptions: {sopt: ['eq','bw','ew','cn']},align: 'center',editrules:{required:true},editoptions: {defaultValue: ' '},formatter: 'text'},
{name:'username',label:'Username',searchoptions: {sopt: ['eq','bw','ew','cn']},width:125,align: 'center' },
{name:'email',label:'Email',width:135,searchoptions: {sopt: ['eq','bw','ew','cn']},align: 'center'},
{name:'sefDepartament',label:'Sef Departament',width:90,editable:true,align: 'center', stype:"select", searchoptions:{sopt: ['eq','ne'],value: "Yes:Yes;No:No"},formatter: checkboxFormatFunc,edittype:'checkbox',editoptions: { dataEvents: checkboxEditOptionEvents,value:'Yes:No', defaultValue: 'No' }},
{name:'position',label:'Position',editable:true,stype: 'select',formatter: 'select',searchoptions: {sopt: ['eq','ne'],value: ' : ;position 1:position 1;position 2:position 2;position 3:position 3;position 4:position 4;position 5:position 5'},
align: 'center',edittype:'select',editoptions:{defaultvalue: 'P0: ',value: ' : ;position 1:position 1;position 2:position 2;position 3:position 3;position 4:position 4;position 5:position 5'},width: 75},
{name:'joinYear',label:'Join Year',formatter:'date', formatoptions: {newformat:'d-m-Y'}, datefmt: 'dd-mm-yyyy', editable:true,searchtype: 'datepicker',align: 'center',width: 70,
searchoptions:{dateFormat:'dd-mm-yy',dataInit: function (elem){
$(elem).datepicker({ showButtonPanel: true, dateFormat: 'yy-mm-dd'});},sopt: ['eq','ne']},
editoptions:{size:20,defaultValue: ' ',dataInit: function (elem) {
$(elem).datepicker({ showButtonPanel: true, dateFormat: 'dd-mm-yy'});
}}},
{name:'experience', label:'Experience', formatter: experienceFunction, searchoptions:{sopt: ['eq','bw','ew','cn']}, editable:'hidden', editoptions:{defaultValue: ' '},align: 'center',width: 60},
{name:'actiuni',label: 'Actiuni',formatter: 'actions', formatoptions: {afterSave:afterSaveFunction},editable: false,sortable: false,search: false,width: 20 }
];
grid.jqGrid({
pager: '#pager',
url: "/RestWithDatabaseConnection/rest/fetchData",
editurl:'/RestWithDatabaseConnection/rest/update',
datatype: "json",
height: 250,
viewrecords: true,
scrollOffset:0,
sortorder: 'asc',
caption:'Employee List' ,
autowidth: true,
colModel: colModelSettings,
beforeSelectRow : function(id){
var idsArray = grid.jqGrid('getDataIDs');
var i;
for(i=0;i<idsArray.length;i++){
if($('#'+idsArray[i]).is('[editable="1"]') ){
grid.editRow(idsArray[i],true);
return false;
}
}
return true;
},
inlineEditing: {
ajaxSaveOptions: { contentType: "application/json" },
serializeSaveData: function (postData) {
var idArray = grid.getCol('id');
var count = 0;
var k = 1;
while(postData.id.search('jqg') != '-1'){
for(var i =0 ; i<idArray.length;i++){
if(k == idArray[i]){
count++;
}
if(count == 0){
postData.id = k ;
break;
}
}
k++;
}
return JSON.stringify(postData);
}
}
});
grid.jqGrid('navGrid', '#pager', {edit:false, add:false, delete:true, save:false, cancel:false, search:true, searchtext: 'Search', refresh:true},
{},{},{
url: '/RestWithDatabaseConnection/rest/delete',
mtype: 'DELETE',
reloadAfterSubmit: true,
ajaxDelOptions: {
contentType: "application/json",
},
serializeDelData: function(postdata) {
return JSON.stringify(postdata);
}},{},{},{},{} );
grid.jqGrid('inlineNav','#pager',
{
edit:true,
edittext: 'Edit',
save:true,
savetext: 'Save',
add:true,
cancel: true,
canceltext: 'Cancel',
cancelicon: 'ui-icon-cancel',
addicon:'ui-icon-plus',
addtext: 'Add',
addedrow: 'last',
addParams: {
position: 'last',
addRowParams: {
aftersavefunc : afterSaveFunction,
keys: true,
}
},
editParams:{
url: '/RestWithDatabaseConnection/rest/update',
mtype : "POST",
keys: true,
aftersavefunc : afterSaveFunction,
}
})})
Edit2 - 服务器对 fetchData 的响应:
[{"id":"3","nume":"Aladin","prenume":"Zoro","username":"Aladin.Zoro","email":"Aladin.Zoro@test.com","sefDepartament":"Yes","position":"position 4","joinYear":"2015-11-08","experience":"2 months"},
{"id":"2","nume":"Harap","prenume":"Alb","username":"Harap.Alb","email":"Harap.Alb@test.com","sefDepartament":"No","position":"position 1","joinYear":"2016-01-03","experience":"9 days "},
{"id":"4","nume":"Don","prenume":"Homa","username":"Don.Homa","email":"Don.Homa@test.com","sefDepartament":"No","position":"position 4","joinYear":"2015-09-06","experience":"4 months"},
{"id":"5","nume":"Dorel","prenume":"Gigel","username":"Dorel.Gigel","email":"Dorel.Gigel@test.com","sefDepartament":"No","position":"position 4","joinYear":"2016-01-10","experience":"2 days"},
{"id":"1","nume":"Ivan","prenume":"Stefan","username":"Ivan.Stefan","email":"Ivan.Stefan@test.com","sefDepartament":"No","position":"position 2","joinYear":"2016-01-10","experience":"2 days"}]
以下是解决您的主要问题和改进您发布的 JavaScript 代码的一些建议。
首先,本地编辑场景需要本地生成新的rowid。应该在服务器 上生成新的 rowids 以防将后端数据保存在数据库中。典型的实现包括将 PRIMARY KEY
定义为 int IDENTITY
in every table。它使 id 唯一且固定。删除某些行并创建新行将永远不会被解释为对旧行的编辑,因为新行将始终获得新的 id,这是以前从未使用过的(在 table 中)。
要利用在服务器端生成的 ID,有两个主要选择:
- 在每次添加行操作后重新加载网格。
- 在编辑时扩展与服务器的通信,服务器 returns 在数据库 table 中生成的新 ID,返回到 jqGrid。在服务器上成功创建行后,可以使用
aftersavefunc
回调(仅用于添加新行)更新 rowid。 RESTful 服务 returns 的许多标准实现在添加或编辑时返回 整行数据 包含 id。可以使用 aftersavefunc
回调中的数据并使用 $("#" + rowid).attr("id", newRowid);
之类的东西来更新新行。它把 id 保存在一些额外的列中(比如你使用隐藏的 id
列)然后应该另外使用 setCell
方法来更新单元格。
第一个选择最简单,我建议你首先实现它。除非重新加载网格不能满足用户,一个接一个地添加很多行,那么你应该多写一点代码来实现第二种情况。
您当前的代码使用 inlineNav
进行添加和编辑操作,使用内联编辑实现,使用方法 navGrid
进行删除操作,使用表单编辑实现。表单编辑,包括删除,默认使用reloadAfterSubmit: true
选项。这意味着在删除每一行后,网格将从服务器(从 url: "/RestWithDatabaseConnection/rest/fetchData"
)重新加载。您可以通过将 afterSaveFunction
替换为以下内容来解决您的主要问题:
var afterSaveFunction = function () {
$(this).trigger("reloadGrid", [{current: true, fromServer: true}]);
};
选项 current
用于在重新加载后保留当前选择,选项 fromServer: true
仅在您另外使用 loadonce: true
选项时才有意义。您可以只使用 navGrid
的 reloadGridOptions: {fromServer: true}
选项强制从服务器 重新加载数据 单击导航栏的 Refresh/Reload 按钮。如果您没有那么多需要在网格中显示的数据(例如少于 1000 行),那么建议使用这种行为。
一些更常见的改进代码的建议:
您可以考虑使用 height: "auto"
而不是 height: 250
并通过指定 rowNum
值来管理网格的最大高度。在这种情况下,将不需要选项 scrollOffset: 0
。
从服务器返回的数据格式看起来如此,您没有实现服务器端分页、排序和过滤。您应该使用 loadonce: true
和 forceClientSorting: true
选项。 loadonce: true
通知 jqGrid 在内部 data
参数中保存 all 从服务器本地返回的数据。您可以随时通过用法 $('#grid').jqGrid("getGridParam", "data")
访问数组。 rowNum
的值(默认值为 20)将用于 local 分页。 sortname
和 sortorder
将用于 local 排序。您将为 local searching/filtering 使用搜索对话框(由 navGrid
添加)或过滤器工具栏(由 filterToolbar
添加)。它简化了服务器代码,从用户的角度提高了网格的性能,并简化了服务器和客户端之间的接口。您可以在服务器上使用经典的 RESTful 界面,无需任何扩展。
另一条评论:我建议您删除不需要的隐藏 id
列 (name:'id', label:'id', key: true, hidden: true, ...
)。关于 rowid 的信息将保存在行(<tr>
元素)的 id
属性中,并且不需要在每一行的隐藏 <td>
元素中保存重复信息。
您的代码还有许多其他部分可以改进。例如,您在服务器端使用的 DELETE 操作看起来很奇怪。您使用 mtype: 'DELETE'
,但您将请求的 正文 内已删除行的 ID 发送到服务器,而不是将其附加到 URL。对应标准,HTTP DELETE 应该包含no body。您可以使用 jqGrid 选项 formDeleting
指定所有删除选项,您可以将 url
参数定义为函数:
formDeleting: {
mtype: "DELETE",
url: function (rowid) {
return "/RestWithDatabaseConnection/rest/delete/" + rowid;
},
ajaxDelOptions: { contentType: "application/json" },
serializeDelData: function () {
return "";
}
}
您需要修改 /RestWithDatabaseConnection/rest/delete/
的服务器代码以使用相同的通信协议并获取从 URL.
中删除的 ID
你可以使用免费jqGrid的navOptions
参数来指定navGrid
的选项:
navOptions: { edit: false, add: false }
(searchtext: 'Search'
和您使用的其他选项似乎有默认值,我在那里删除了)。
即将结束根据 REST 标准,可以使用 HTTP PUT 操作进行行编辑,使用 HTTP POST 添加新行。您应该在后端为这两个操作实现 不同的 入口点。您已经使用 /RestWithDatabaseConnection/rest/update
并且可以实现 /RestWithDatabaseConnection/rest/create
来添加新行。例如,您可以使用以下 inlineEditing
更改来实现场景:
inlineNavOptions: { add: true, edit: true },
inlineEditing: {
url: function (id, editOrAdd) {
return "/RestWithDatabaseConnection/rest/" +
(editOrAdd === "edit" ? "update" : "create");
},
mtype: function (editOrAdd) {
return editOrAdd === "edit" ? "PUT" : "POST";
},
keys: true,
serializeSaveData: function (postData) {
return JSON.stringify(dataToSend);
},
aftersavefunc: function () {
$(this).trigger("reloadGrid", [{current: true, fromServer: true}]);
},
addParams: {
addRowParams: {
position: "last",
serializeSaveData: function (postData) {
var dataToSend = $.extend({}, postData);
// don't send any id in case of creating new row
// or to send `0`:
delete dataToSend.id; // or dataToSend.id = 0;
return JSON.stringify(dataToSend);
}
}
}
}
我正在尝试为添加到我的 jqGrid 中的新行分配一个唯一 ID。我使用免费的 jqGrid 4.11.0,服务器端的 java 休息服务和数据库的 MS SQL。
inlineEditing: {
ajaxSaveOptions: { contentType: "application/json" },
serializeSaveData: function (postData) {
var idArray = grid.getCol('id');
var count = 0;
var k = 1;
while(postData.id.search('jqg') != '-1'){
for(var i =0 ; i<idArray.length;i++){
if(k == idArray[i]){
count++;
}
if(count == 0){
postData.id = k ;
break;
}
}
k++;
}
return JSON.stringify(postData);
}
}
我注意到 jqGrid 给出的默认 ID 是 jqg + 一个数字。关于如何制作当前未在任何数据库记录上使用的唯一 ID 的任何建议?我应该从服务器端执行此操作还是可以在 jqGrid 代码中执行此操作?
在晚上的某个时候,这段代码有点工作,并继续为所有新行提供 id 7 [即使它应该继续增加]。经过一些更改[不记得有什么更改],每次我单击保存将新行提交到服务器时,页面冻结并且 chrome 建议我应该终止进程。
请让我知道什么以及是否应该添加更多信息。
编辑 1:
$(function () {
var grid = $('#grid'),
checkboxEditOptionEvents = [
{type : 'click', data: {'Yes': 'Yes'}, fn: function (e, id) {
var checkboxCol = grid.getCol('sefDepartament'),
ids = grid.jqGrid('getDataIDs'),
numberOfCheckedBoxes = [],
k;
for (k = 0; k < ids.length; k++) {
if(checkboxCol[k] == 'Yes'){
numberOfCheckedBoxes.push(checkboxCol[k]);
if (numberOfCheckedBoxes.length == 1){
alert('Please deselect the other checked box first');
$(this).prop("checked",false);
numberOfCheckedBoxes = 0;
}
}
}
}}];
var experienceFunction = function(cellvalue, options ,rowObject){
var joinYearVar = rowObject.joinYear,
YY = joinYearVar.slice(0,4),
MM = joinYearVar.slice(5,7),
DD= joinYearVar.slice(8,11);
return moment("\"" +YY+MM+DD+"\"" , "YYYYMMDD").fromNow();
};
var checkboxFormatFunc = function(cellvalue, options ,rowObject){
if(cellvalue == 'Yes'){
return 'Yes';
}
return 'No';
};
var afterSaveFunction = function(id){
var prenumeVar = grid.getCell(id, 'prenume').trim(),
numeVar = grid.getCell(id,'nume').trim(),
usernameVar = numeVar +'.'+ prenumeVar,
emailVar = usernameVar + '@test.com';
usernameVar =usernameVar.replace(/\s/g , '').trim();
emailVar = emailVar.replace(/\s/g , '');
grid.setCell(id, 'username', usernameVar);
grid.setCell(id, 'email', emailVar);
};
var colModelSettings = [
{name:'id', label:'id',key: true,hidden: true, width:10,sorttype:'number',editable: false},
{name:'nume',label:'Nume',width:90, align: 'center',editable:true,searchoptions: {sopt: ['eq','bw','ew','cn']}, editrules:{required:true}, editoptions: {defaultValue: ' '},formatter: 'text'},
{name:'prenume',label:'Prenume',width:100,editable:true,searchoptions: {sopt: ['eq','bw','ew','cn']},align: 'center',editrules:{required:true},editoptions: {defaultValue: ' '},formatter: 'text'},
{name:'username',label:'Username',searchoptions: {sopt: ['eq','bw','ew','cn']},width:125,align: 'center' },
{name:'email',label:'Email',width:135,searchoptions: {sopt: ['eq','bw','ew','cn']},align: 'center'},
{name:'sefDepartament',label:'Sef Departament',width:90,editable:true,align: 'center', stype:"select", searchoptions:{sopt: ['eq','ne'],value: "Yes:Yes;No:No"},formatter: checkboxFormatFunc,edittype:'checkbox',editoptions: { dataEvents: checkboxEditOptionEvents,value:'Yes:No', defaultValue: 'No' }},
{name:'position',label:'Position',editable:true,stype: 'select',formatter: 'select',searchoptions: {sopt: ['eq','ne'],value: ' : ;position 1:position 1;position 2:position 2;position 3:position 3;position 4:position 4;position 5:position 5'},
align: 'center',edittype:'select',editoptions:{defaultvalue: 'P0: ',value: ' : ;position 1:position 1;position 2:position 2;position 3:position 3;position 4:position 4;position 5:position 5'},width: 75},
{name:'joinYear',label:'Join Year',formatter:'date', formatoptions: {newformat:'d-m-Y'}, datefmt: 'dd-mm-yyyy', editable:true,searchtype: 'datepicker',align: 'center',width: 70,
searchoptions:{dateFormat:'dd-mm-yy',dataInit: function (elem){
$(elem).datepicker({ showButtonPanel: true, dateFormat: 'yy-mm-dd'});},sopt: ['eq','ne']},
editoptions:{size:20,defaultValue: ' ',dataInit: function (elem) {
$(elem).datepicker({ showButtonPanel: true, dateFormat: 'dd-mm-yy'});
}}},
{name:'experience', label:'Experience', formatter: experienceFunction, searchoptions:{sopt: ['eq','bw','ew','cn']}, editable:'hidden', editoptions:{defaultValue: ' '},align: 'center',width: 60},
{name:'actiuni',label: 'Actiuni',formatter: 'actions', formatoptions: {afterSave:afterSaveFunction},editable: false,sortable: false,search: false,width: 20 }
];
grid.jqGrid({
pager: '#pager',
url: "/RestWithDatabaseConnection/rest/fetchData",
editurl:'/RestWithDatabaseConnection/rest/update',
datatype: "json",
height: 250,
viewrecords: true,
scrollOffset:0,
sortorder: 'asc',
caption:'Employee List' ,
autowidth: true,
colModel: colModelSettings,
beforeSelectRow : function(id){
var idsArray = grid.jqGrid('getDataIDs');
var i;
for(i=0;i<idsArray.length;i++){
if($('#'+idsArray[i]).is('[editable="1"]') ){
grid.editRow(idsArray[i],true);
return false;
}
}
return true;
},
inlineEditing: {
ajaxSaveOptions: { contentType: "application/json" },
serializeSaveData: function (postData) {
var idArray = grid.getCol('id');
var count = 0;
var k = 1;
while(postData.id.search('jqg') != '-1'){
for(var i =0 ; i<idArray.length;i++){
if(k == idArray[i]){
count++;
}
if(count == 0){
postData.id = k ;
break;
}
}
k++;
}
return JSON.stringify(postData);
}
}
});
grid.jqGrid('navGrid', '#pager', {edit:false, add:false, delete:true, save:false, cancel:false, search:true, searchtext: 'Search', refresh:true},
{},{},{
url: '/RestWithDatabaseConnection/rest/delete',
mtype: 'DELETE',
reloadAfterSubmit: true,
ajaxDelOptions: {
contentType: "application/json",
},
serializeDelData: function(postdata) {
return JSON.stringify(postdata);
}},{},{},{},{} );
grid.jqGrid('inlineNav','#pager',
{
edit:true,
edittext: 'Edit',
save:true,
savetext: 'Save',
add:true,
cancel: true,
canceltext: 'Cancel',
cancelicon: 'ui-icon-cancel',
addicon:'ui-icon-plus',
addtext: 'Add',
addedrow: 'last',
addParams: {
position: 'last',
addRowParams: {
aftersavefunc : afterSaveFunction,
keys: true,
}
},
editParams:{
url: '/RestWithDatabaseConnection/rest/update',
mtype : "POST",
keys: true,
aftersavefunc : afterSaveFunction,
}
})})
Edit2 - 服务器对 fetchData 的响应:
[{"id":"3","nume":"Aladin","prenume":"Zoro","username":"Aladin.Zoro","email":"Aladin.Zoro@test.com","sefDepartament":"Yes","position":"position 4","joinYear":"2015-11-08","experience":"2 months"},
{"id":"2","nume":"Harap","prenume":"Alb","username":"Harap.Alb","email":"Harap.Alb@test.com","sefDepartament":"No","position":"position 1","joinYear":"2016-01-03","experience":"9 days "},
{"id":"4","nume":"Don","prenume":"Homa","username":"Don.Homa","email":"Don.Homa@test.com","sefDepartament":"No","position":"position 4","joinYear":"2015-09-06","experience":"4 months"},
{"id":"5","nume":"Dorel","prenume":"Gigel","username":"Dorel.Gigel","email":"Dorel.Gigel@test.com","sefDepartament":"No","position":"position 4","joinYear":"2016-01-10","experience":"2 days"},
{"id":"1","nume":"Ivan","prenume":"Stefan","username":"Ivan.Stefan","email":"Ivan.Stefan@test.com","sefDepartament":"No","position":"position 2","joinYear":"2016-01-10","experience":"2 days"}]
以下是解决您的主要问题和改进您发布的 JavaScript 代码的一些建议。
首先,本地编辑场景需要本地生成新的rowid。应该在服务器 上生成新的 rowids 以防将后端数据保存在数据库中。典型的实现包括将 PRIMARY KEY
定义为 int IDENTITY
in every table。它使 id 唯一且固定。删除某些行并创建新行将永远不会被解释为对旧行的编辑,因为新行将始终获得新的 id,这是以前从未使用过的(在 table 中)。
要利用在服务器端生成的 ID,有两个主要选择:
- 在每次添加行操作后重新加载网格。
- 在编辑时扩展与服务器的通信,服务器 returns 在数据库 table 中生成的新 ID,返回到 jqGrid。在服务器上成功创建行后,可以使用
aftersavefunc
回调(仅用于添加新行)更新 rowid。 RESTful 服务 returns 的许多标准实现在添加或编辑时返回 整行数据 包含 id。可以使用aftersavefunc
回调中的数据并使用$("#" + rowid).attr("id", newRowid);
之类的东西来更新新行。它把 id 保存在一些额外的列中(比如你使用隐藏的id
列)然后应该另外使用setCell
方法来更新单元格。
第一个选择最简单,我建议你首先实现它。除非重新加载网格不能满足用户,一个接一个地添加很多行,那么你应该多写一点代码来实现第二种情况。
您当前的代码使用 inlineNav
进行添加和编辑操作,使用内联编辑实现,使用方法 navGrid
进行删除操作,使用表单编辑实现。表单编辑,包括删除,默认使用reloadAfterSubmit: true
选项。这意味着在删除每一行后,网格将从服务器(从 url: "/RestWithDatabaseConnection/rest/fetchData"
)重新加载。您可以通过将 afterSaveFunction
替换为以下内容来解决您的主要问题:
var afterSaveFunction = function () {
$(this).trigger("reloadGrid", [{current: true, fromServer: true}]);
};
选项 current
用于在重新加载后保留当前选择,选项 fromServer: true
仅在您另外使用 loadonce: true
选项时才有意义。您可以只使用 navGrid
的 reloadGridOptions: {fromServer: true}
选项强制从服务器 重新加载数据 单击导航栏的 Refresh/Reload 按钮。如果您没有那么多需要在网格中显示的数据(例如少于 1000 行),那么建议使用这种行为。
一些更常见的改进代码的建议:
您可以考虑使用 height: "auto"
而不是 height: 250
并通过指定 rowNum
值来管理网格的最大高度。在这种情况下,将不需要选项 scrollOffset: 0
。
从服务器返回的数据格式看起来如此,您没有实现服务器端分页、排序和过滤。您应该使用 loadonce: true
和 forceClientSorting: true
选项。 loadonce: true
通知 jqGrid 在内部 data
参数中保存 all 从服务器本地返回的数据。您可以随时通过用法 $('#grid').jqGrid("getGridParam", "data")
访问数组。 rowNum
的值(默认值为 20)将用于 local 分页。 sortname
和 sortorder
将用于 local 排序。您将为 local searching/filtering 使用搜索对话框(由 navGrid
添加)或过滤器工具栏(由 filterToolbar
添加)。它简化了服务器代码,从用户的角度提高了网格的性能,并简化了服务器和客户端之间的接口。您可以在服务器上使用经典的 RESTful 界面,无需任何扩展。
另一条评论:我建议您删除不需要的隐藏 id
列 (name:'id', label:'id', key: true, hidden: true, ...
)。关于 rowid 的信息将保存在行(<tr>
元素)的 id
属性中,并且不需要在每一行的隐藏 <td>
元素中保存重复信息。
您的代码还有许多其他部分可以改进。例如,您在服务器端使用的 DELETE 操作看起来很奇怪。您使用 mtype: 'DELETE'
,但您将请求的 正文 内已删除行的 ID 发送到服务器,而不是将其附加到 URL。对应标准,HTTP DELETE 应该包含no body。您可以使用 jqGrid 选项 formDeleting
指定所有删除选项,您可以将 url
参数定义为函数:
formDeleting: {
mtype: "DELETE",
url: function (rowid) {
return "/RestWithDatabaseConnection/rest/delete/" + rowid;
},
ajaxDelOptions: { contentType: "application/json" },
serializeDelData: function () {
return "";
}
}
您需要修改 /RestWithDatabaseConnection/rest/delete/
的服务器代码以使用相同的通信协议并获取从 URL.
你可以使用免费jqGrid的navOptions
参数来指定navGrid
的选项:
navOptions: { edit: false, add: false }
(searchtext: 'Search'
和您使用的其他选项似乎有默认值,我在那里删除了)。
即将结束根据 REST 标准,可以使用 HTTP PUT 操作进行行编辑,使用 HTTP POST 添加新行。您应该在后端为这两个操作实现 不同的 入口点。您已经使用 /RestWithDatabaseConnection/rest/update
并且可以实现 /RestWithDatabaseConnection/rest/create
来添加新行。例如,您可以使用以下 inlineEditing
更改来实现场景:
inlineNavOptions: { add: true, edit: true },
inlineEditing: {
url: function (id, editOrAdd) {
return "/RestWithDatabaseConnection/rest/" +
(editOrAdd === "edit" ? "update" : "create");
},
mtype: function (editOrAdd) {
return editOrAdd === "edit" ? "PUT" : "POST";
},
keys: true,
serializeSaveData: function (postData) {
return JSON.stringify(dataToSend);
},
aftersavefunc: function () {
$(this).trigger("reloadGrid", [{current: true, fromServer: true}]);
},
addParams: {
addRowParams: {
position: "last",
serializeSaveData: function (postData) {
var dataToSend = $.extend({}, postData);
// don't send any id in case of creating new row
// or to send `0`:
delete dataToSend.id; // or dataToSend.id = 0;
return JSON.stringify(dataToSend);
}
}
}
}