2011-04-10 93 views
6

似乎有很多解决方案非常接近解决我的问题,但几十个和几十个问题我倒过来不是一个似乎完全解决我的问题,米试图做。虽然我看到几乎相同的问题没有答案。我尝试过很多选项和功能的组合,但无济于事。仅在客户端上使用模式表单向jqGrid添加新行

我想使用模态表单来添加一个新的行与输入的值到jqGrid但我不希望它发布到服务器上提交。我确实希望最终发布到服务器,但是只有在客户端用户对从模式表单添加的行执行了额外编辑(如果需要)之后。我不希望任何行保存到远程数据库,直到客户端执行了一些编辑操作,然后动态更新其他列。一旦确认了某些值的状态,就会显示一个“保存”按钮,并且可以将网格行发布到服务器。除非符合此验证条件,否则不会将该行提交给数据库。我有一些jqGrids在我的应用程序中的其他地方使用,它们会发布已提交的模式表单的新行数据,但是我试图用不直接涉及服务器的客户机完成不同的事情。我喜欢模式表单的更直观的界面,以便与客户端用户初始输入值,然后编辑内联新行的字段(如果需要的话),这是我必须提出的问题:我是否可以只将表格提交为新行发生任何发布到服务器的动作?

我在jqGrid Wiki资源中看到一个用户发表的评论,他说如果“clientArray”是使用Grids模式表单提交选项输入的值“editurl:”clientArray“,模式表单不会吐出”没有URL被设置“的消息,但它仍然没有,并且一个新行没有添加到网格中。我已经将Grid数据类型设置为本地”数据类型:'clientSide'“,但获得相同的”未设置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 
    }) 
}); 

我希望这是相当明确的。看起来应该是相当简单的使用模式形式添加一行而不立即发布到服务器,但我无法解决这个问题。并请大家多多,如果我不及时点击图标答案给予适当的信贷,但我会当我知道点击什么,所以请相应的建议。 :) 非常感谢提前。 杰里

回答

14

当前版本的形式编辑的不支持本地数据类型。尽管如此,如果使用更长的代码,可以实现这一点。我前段时间创建了the demo,并发布了here建议在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工作,我张贴在the answer

更新2The answer为4.5.4提供更新。

更新12:新版本4.7的jqGrid的支持形成了现在的本地数据的编辑。使用新版本的相应演示是here。我只需要添加新的reformatAfterEdit: true选项formatter: "date"Another demo使用jqGrid 4.6。

+0

谢谢你@ Oleg。 – 2012-04-05 09:23:34

+0

@Frank:不客气! – Oleg 2012-04-05 17:57:46

+0

@Oleg - 正是我需要的。不幸的是,它似乎不再适用于jqGrid 4.6或4.7。即使表单中有数据,表单也不会重置,然后出现“客户端需要”错误 – MSquared 2014-12-10 23:23:19

1

编辑 为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错误