6

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

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

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

4

2 回答 2

14

当前版本的表单编辑不支持本地数据类型。不过,如果使用更长的代码,则可以实现。我前段时间创建了演示,并在此处发布了在 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 现在支持本地数据的表单编辑。使用新版本的相应演示在这里。我只需要reformatAfterEdit: true添加formatter: "date". 另一个演示使用 jqGrid 4.6。

于 2011-04-10T11:43:15.683 回答
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错误

于 2012-04-16T07:40:26.033 回答