Добавление новой строки в jqGrid с помощью модальной формы только на клиенте
Кажется, что есть много решений, которые очень близки к решению моей проблемы, но из десятков и десятков вопросов, которые я вылил, ни один, кажется, точно не касается того, что я пытаюсь сделать. Хотя я видел почти такой же вопрос без ответа. Я пробовал так много комбинаций опций и функций безрезультатно.
Я хочу использовать модальную форму для добавления новой строки с введенными значениями в jqGrid, но я не хочу, чтобы она публиковалась на сервере после отправки. Я хочу в конечном итоге опубликовать на сервере, но только после того, как пользователь клиента выполнил дополнительное редактирование (при необходимости) в строке(строках), добавленной из модальной формы. Я не хочу, чтобы строки сохранялись в удаленной базе данных, пока клиент не выполнит некоторые изменения, которые, в свою очередь, динамически обновляют другие столбцы. После проверки определенного состояния значений отображается кнопка Сохранить и строки сетки могут быть разнесены на сервер. Если это проверенное условие не выполнено, строки не подлежит представлению в базу данных. У меня есть ряд jqGrids, используемых в другом месте в моем приложении, которые публикуют новые данные строк представленной модальной формы, но эта сетка я пытаюсь выполнить что-то другое с клиентом, который не сразу включает сервер. Мне нравится более интуитивный интерфейс модальной формы для начального ввода значений с пользователем клиента, а затем редактирование встроенных полей новой строки, если это необходимо, что потребовало моего вопроса: Могу ли я отправить форму как новая строка только без каких-либо действий по проводке на сервер?
Я видел в Вики-ресурсе jqGrid комментарий, сделанный пользователем, который сказал, что если "clientArray" - это значение, введенное для использования опции отправки модальной формы сеток "editurl:" clientArray", что модальная форма не будет плевать сообщение" Нет URL-адреса", но он все еще делает, и новая строка не добавляется в сетку. Я сделал тип данных сетки как локальный "тип данных: " на стороне клиента", но получаю то же сообщение об ошибке" нет URL-адреса". Сценарий довольно прост для модальной формы, которая вызывается пользовательской кнопкой следующим образом:
(опции "footerrow, userDataOnFooter и altRows" включены как часть обновления значений в сводном нижнем колонтитуле, который связан с редактированием, выполняемым над ячейками новой строки(строк), добавляемой через модальную форму)
jQuery("#grid_test").jqGrid({
url:'/grid_test_url.asp?id=' + vId,
datatype: "clientSide",
colNames: ['ID','Col 1', 'Col 2', 'Col 3','Col 4'],
colModel: [
{name:'id',index:'id',width:90,align:"center",editable:true,editoptions:{size:25}, formoptions: {...}, editrules: {...}},
{name:'col1',index:'col1',width:130,align:"right",editable:true,editoptions:{size:25}, formoptions: {}, editrules: {}},
{name:'col2',index:'col2',width:130,align:"right",editable:true,editoptions:{size: 25}, formoptions: {}, editrules: {}},
{name:'col3',index:'col3',width:130,align:"right",editable: true,editoptions:{size:25}, formoptions: {}, editrules: {}},
{name:'col4',index:'col4',width:130,align:"right",editable:true,editoptions:{ size: 25 }, formoptions: {}, editrules: {}}
],
rowNum:5,
rowList:[5,10,20],
pager: '#pgrid_test',
toolbar: [true, "top"],
editurl: '', //not sure what would go here to block attempted post by the Submit action of the modal form
width: 500,
sortname: 'id',
viewrecords: true,
sortorder: "asc",
multiselect: true,
cellEdit: true,
caption: "Grid Test Add New Row",
footerrow: true,
userDataOnFooter: true,
altRows: true
})
jQuery("#grid_test").jqGrid('navGrid', '#pgrid_test', { add: false, edit: false, del: false })
//append custom button
$("#t_grid_test").append("<input type='button' class='add' value='Add New Row' style='height:20px; color:green; font-size:11px;' />");
$("input.add", "#t_grid_test").click(function () {
jQuery("#grid_test").jqGrid('editGridRow', "new", {
jqModal: true,
savekey: [true, 13],
navkeys: [true, 38, 40],
bottominfo: "Fields marked with (*) are required. ",
addCaption: 'New Row Values',
width: 300,
dataheight: 200,
recreateForm: true,
//checkOnUpdate: true,
//checkOnSubmit: true,
//reloadAfterSubmit: true,
closeOnEscape: true,
closeAfterAdd: true
//clearAfterAdd: true
})
});
Я надеюсь, это достаточно ясно. Кажется, довольно просто добавить строку, используя модальную форму без нее немедленно отправляю на сервер, но я не могу выработать решение. И, пожалуйста, терпите, если я не быстро нажимаю значки для надлежащего кредита, данного для ответов, но я буду, когда я знаю, что нажать, поэтому, пожалуйста, сообщите соответственно. :) Большое спасибо заранее. Джерри!--2-->
2 ответов
текущая версия редактирования формы не поддерживает локальный тип данных. Тем не менее можно реализовать, если с немного более длинный код. Я создал демо некоторое время назад и написал здесь предложение реализовать локальную поддержку редактирования в jqGrid. До сих пор он еще не реализован, но вы можете использовать мой пример для реализации того, что вам нужно.
Я включил код ниже:
var lastSel, mydata = [
{id:"1", invdate:"2007-10-01",name:"test", note:"note", amount:"200.00",tax:"10.00",closed:true, ship_via:"TN",total:"210.00"},
{id:"2", invdate:"2007-10-02",name:"test2", note:"note2", amount:"300.00",tax:"20.00",closed:false,ship_via:"FE",total:"320.00"},
{id:"3", invdate:"2007-09-01",name:"test3", note:"note3", amount:"400.00",tax:"30.00",closed:false,ship_via:"FE",total:"430.00"},
{id:"4", invdate:"2007-10-04",name:"test4", note:"note4", amount:"200.00",tax:"10.00",closed:true ,ship_via:"TN",total:"210.00"},
{id:"5", invdate:"2007-10-31",name:"test5", note:"note5", amount:"300.00",tax:"20.00",closed:false,ship_via:"FE",total:"320.00"},
{id:"6", invdate:"2007-09-06",name:"test6", note:"note6", amount:"400.00",tax:"30.00",closed:false,ship_via:"FE",total:"430.00"},
{id:"7", invdate:"2007-10-04",name:"test7", note:"note7", amount:"200.00",tax:"10.00",closed:true ,ship_via:"TN",total:"210.00"},
{id:"8", invdate:"2007-10-03",name:"test8", note:"note8", amount:"300.00",tax:"20.00",closed:false,ship_via:"FE",total:"320.00"},
{id:"9", invdate:"2007-09-01",name:"test9", note:"note9", amount:"400.00",tax:"30.00",closed:false,ship_via:"TN",total:"430.00"},
{id:"10",invdate:"2007-09-08",name:"test10",note:"note10",amount:"500.00",tax:"30.00",closed:true ,ship_via:"TN",total:"530.00"},
{id:"11",invdate:"2007-09-08",name:"test11",note:"note11",amount:"500.00",tax:"30.00",closed:false,ship_via:"FE",total:"530.00"},
{id:"12",invdate:"2007-09-10",name:"test12",note:"note12",amount:"500.00",tax:"30.00",closed:false,ship_via:"FE",total:"530.00"}
],
grid = $("#list"),
onclickSubmitLocal = function(options,postdata) {
var grid_p = grid[0].p,
idname = grid_p.prmNames.id,
grid_id = grid[0].id,
id_in_postdata = grid_id+"_id",
rowid = postdata[id_in_postdata],
addMode = rowid === "_empty",
oldValueOfSortColumn;
// postdata has row id property with another name. we fix it:
if (addMode) {
// generate new id
var new_id = grid_p.records + 1;
while ($("#"+new_id).length !== 0) {
new_id++;
}
postdata[idname] = String(new_id);
} else if (typeof(postdata[idname]) === "undefined") {
// set id property only if the property not exist
postdata[idname] = rowid;
}
delete postdata[id_in_postdata];
// prepare postdata for tree grid
if(grid_p.treeGrid === true) {
if(addMode) {
var tr_par_id = grid_p.treeGridModel === 'adjacency' ? grid_p.treeReader.parent_id_field : 'parent_id';
postdata[tr_par_id] = grid_p.selrow;
}
$.each(grid_p.treeReader, function (i){
if(postdata.hasOwnProperty(this)) {
delete postdata[this];
}
});
}
// decode data if there encoded with autoencode
if(grid_p.autoencode) {
$.each(postdata,function(n,v){
postdata[n] = $.jgrid.htmlDecode(v); // TODO: some columns could be skipped
});
}
// save old value from the sorted column
oldValueOfSortColumn = grid_p.sortname === "" ? undefined: grid.jqGrid('getCell',rowid,grid_p.sortname);
// save the data in the grid
if (grid_p.treeGrid === true) {
if (addMode) {
grid.jqGrid("addChildNode",rowid,grid_p.selrow,postdata);
} else {
grid.jqGrid("setTreeRow",rowid,postdata);
}
} else {
if (addMode) {
grid.jqGrid("addRowData",rowid,postdata,options.addedrow);
} else {
grid.jqGrid("setRowData",rowid,postdata);
}
}
if ((addMode && options.closeAfterAdd) || (!addMode && options.closeAfterEdit)) {
// close the edit/add dialog
$.jgrid.hideModal("#editmod"+grid_id,
{gb:"#gbox_"+grid_id,jqm:options.jqModal,onClose:options.onClose});
}
if (postdata[grid_p.sortname] !== oldValueOfSortColumn) {
// if the data are changed in the column by which are currently sorted
// we need resort the grid
setTimeout(function() {
grid.trigger("reloadGrid", [{current:true}]);
},100);
}
// !!! the most important step: skip ajax request to the server
this.processing = true;
return {};
},
editSettings = {
//recreateForm:true,
jqModal:false,
reloadAfterSubmit:false,
closeOnEscape:true,
savekey: [true,13],
closeAfterEdit:true,
onclickSubmit:onclickSubmitLocal
},
addSettings = {
//recreateForm:true,
jqModal:false,
reloadAfterSubmit:false,
savekey: [true,13],
closeOnEscape:true,
closeAfterAdd:true,
onclickSubmit:onclickSubmitLocal
},
delSettings = {
// because I use "local" data I don't want to send the changes to the server
// so I use "processing:true" setting and delete the row manually in onclickSubmit
onclickSubmit: function(options) { //, rowid) {
var grid_id = grid[0].id,
grid_p = grid[0].p,
newPage = grid_p.page,
rowids = grid_p.multiselect? grid_p.selarrrow: [grid_p.selrow];
// reset the value of processing option to true
// because the value can be changed by jqGrid
options.processing = true;
// delete selected row/rows (multiselect:true)
$.each(rowids, function () {
grid.delRowData(this);
});
// delete the row
//grid.delRowData(rowid);
$.jgrid.hideModal("#delmod"+grid_id,
{gb:"#gbox_"+grid_id,jqm:options.jqModal,onClose:options.onClose});
if (grid_p.lastpage > 1) {// on the multipage grid reload the grid
if (grid_p.reccount === 0 && newPage === grid_p.lastpage) {
// if after deliting there are no rows on the current page
// which is the last page of the grid
newPage--; // go to the previous page
}
// reload grid to make the row from the next page visable.
grid.trigger("reloadGrid", [{page:newPage}]);
}
return true;
},
processing:true
},
initDateEdit = function(elem) {
setTimeout(function() {
$(elem).datepicker({
dateFormat: 'dd-M-yy',
autoSize: true,
showOn: 'button', // it dosn't work in searching dialog
changeYear: true,
changeMonth: true,
showButtonPanel: true,
showWeek: true
});
//$(elem).focus();
},100);
},
initDateSearch = function(elem) {
setTimeout(function() {
$(elem).datepicker({
dateFormat: 'dd-M-yy',
autoSize: true,
//showOn: 'button', // it dosn't work in searching dialog
changeYear: true,
changeMonth: true,
showButtonPanel: true,
showWeek: true
});
//$(elem).focus();
},100);
};
grid.jqGrid({
datatype:'local',
data: mydata,
colNames:['Inv No','Date','Client','Amount','Tax','Total','Closed','Shipped via','Notes'],
colModel:[
{name:'id',index:'id',width:70,align:'center',sorttype: 'int',searchoptions:{sopt:['eq','ne']}},
{name:'invdate',index:'invdate',width:80, align:'center', sorttype:'date',
formatter:'date', formatoptions: {newformat:'d-M-Y'}, editable:true, datefmt: 'd-M-Y',
editoptions: {dataInit:initDateEdit},
searchoptions: {dataInit:initDateSearch}},
{name:'name',index:'name',editable: true, width:70, editrules:{required:true}},
{name:'amount',index:'amount',width:100, formatter:'number', editable: true, align:'right'},
{name:'tax',index:'tax',width:70, formatter:'number', editable: true, align:'right'},
{name:'total',index:'total',width:120, formatter:'number', editable: true, align:'right'},
{name:'closed',index:'closed',width:110,align:'center',editable: true, formatter: 'checkbox',
edittype:'checkbox',editoptions:{value:'Yes:No',defaultValue:'Yes'},
stype: 'select', searchoptions: { sopt:['eq','ne'], value:':All;true:Yes;false:No' }},
{name:'ship_via',index:'ship_via',width:120,align:'center',editable: true, formatter:'select',
edittype:'select',editoptions:{value:'FE:FedEx;TN:TNT;IN:Intim', defaultValue:'Intime'},
stype:'select', searchoptions:{value:':All;FE:FedEx;TN:TNT;IN:Intim'}},
{name:'note',index:'note',width:100,sortable:false,editable:true,edittype:'textarea'}
],
rowNum:10,
rowList:[5,10,20],
pager: '#pager',
gridview:true,
rownumbers:true,
autoencode:true,
ignoreCase:true,
sortname: 'invdate',
viewrecords: true,
sortorder: 'desc',
caption:'How to implement local form editing',
height: '100%',
editurl: 'clientArray',
ondblClickRow: function(rowid, ri, ci) {
var p = grid[0].p;
if (p.selrow !== rowid) {
// prevent the row from be unselected on double-click
// the implementation is for "multiselect:false" which we use,
// but one can easy modify the code for "multiselect:true"
grid.jqGrid('setSelection', rowid);
}
grid.jqGrid('editGridRow', rowid, editSettings);
},
onSelectRow: function(id) {
if (id && id !== lastSel) {
// cancel editing of the previous selected row if it was in editing state.
// jqGrid hold intern savedRow array inside of jqGrid object,
// so it is safe to call restoreRow method with any id parameter
// if jqGrid not in editing state
if (typeof lastSel !== "undefined") {
grid.jqGrid('restoreRow',lastSel);
}
lastSel = id;
}
}
}).jqGrid('navGrid','#pager',{},editSettings,addSettings,delSettings,
{multipleSearch:true,overlay:false,
onClose:function(form){
// if we close the search dialog during the datapicker are opened
// the datepicker will stay opened. To fix this we have to hide
// the div used by datepicker
$("div#ui-datepicker-div.ui-datepicker").hide();
}});
обновлено: изменить код для работы с jqGrid 4.4.1 я разместил в ответ.
обновлено 2: ответ обновить 4.5.4.
обновлено 3: новая версия 4.7 jqGrid теперь поддерживает редактирование локальных данных. Соответствующая демо-версия, которая использует новую версию, -здесь. Мне нужно просто добавить новый на formatter: "date"
. еще одна демонстрация использует jqGrid 4.6.
изменить
as 4.3.2
происходит изменение поведения сетки
С 4.3.1
onclickSubmitLocal = function(options,postdata) {
....
// !!! the most important step: skip ajax request to the server
this.processing = true;
return {};
С 4.3.2
onclickSubmitLocal = function(options,postdata) {
....
// !!! the most important step: skip ajax request to the server
options.processing = true;
return {};
в противном случае сетка возвращает ошибку url