【问题标题】:Adding new row to jqGrid using modal form on client only仅在客户端上使用模式形式向 jqGrid 添加新行
【发布时间】:2011-08-02 10:27:19
【问题描述】:

似乎有许多解决方案非常接近解决我的问题,但在我提出的几十个问题中,没有一个似乎完全解决了我正在尝试做的事情。尽管我已经看到几乎相同的问题没有答案。我尝试了很多选项和功能的组合都无济于事。

我想使用模态表单将带有输入值的新行添加到 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
    })
});

我希望这是相当清楚的。似乎使用模态表单添加一行而不立即发布到服务器应该相当简单,但我无法制定解决方案。如果我没有及时点击图标以获得正确的答案以获得答案,请耐心等待,但当我知道点击什么时我会这样做,因此请提供相应的建议。 :) 提前谢谢了。 杰瑞

【问题讨论】:

    标签: jqgrid local editing form-editing


    【解决方案1】:

    当前版本的表单编辑不支持本地数据类型。不过,如果使用更长的代码,则可以实现。我前段时间创建了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();
               }});
    

    更新:我在the answer 中发布的代码更改为适用于 jqGrid 4.4.1。

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

    更新 3:新的 4.7 版本的 jqGrid 现在支持本地数据的表单编辑。使用新版本的对应demo是here。我只需要添加formatter: "date" 的新reformatAfterEdit: true 选项。 Another demo 使用 jqGrid 4.6。

    【讨论】:

    • @Oleg - 正是我所需要的。不幸的是,它似乎不再适用于 jqGrid 4.6 或 4.7。即使表单中有数据,表单也不会重置,然后出现“需要客户端”错误,
    • @MSquared:究竟应该怎么做才能重现这个问题? (行编辑,添加新行或删除行)。我试过the demo,我刚刚替换了jqGrid,我可以重现任何问题。我使用 UPDATED 2 中引用的演示作为模板。
    • @MSquared:请参阅我的回答的 UPDATED 3 部分。
    • 太棒了!很关心。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-21
      • 1970-01-01
      • 1970-01-01
      • 2012-07-03
      • 2019-10-09
      相关资源
      最近更新 更多