免费jqgrid升级后如何修复表单编辑中的重复表单键 [英] How to fix duplicate form key post in form edit after free jqgrid upgrade

查看:331
本文介绍了免费jqgrid升级后如何修复表单编辑中的重复表单键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



例如使用testcase下面的帖子数据包含:

  ------ WebKitFormBoundaryHjeY1fJPAaaXE56n 
Content-Disposition:form-data; NAME = Pilt;文件名=eeva.bmp
内容类型:image / bmp


------ WebKitFormBoundaryHjeY1fJPAaaXE56n
Content-Disposition:form-data; name =_ image_Pilt


------ WebKitFormBoundaryHjeY1fJPAaaXE56n
Content-Disposition:form-data; name =Pilt

注意 name =Pilt出现在两次。



要重现,请在Chrome中打开以下代码,选择行,开始表单编辑,选择一些图像,激活chrome开发人员工具,然后按提交按钮。
请求有效载荷显示已经发布了重复的Pilt键。



如何解决这个问题,以便在早期版本中没有重复的键?



测试用例:

 <!DOCTYPE html> 
< html lang =en>
< head>
< meta charset =utf-8>
< meta http-equiv =X-UA-Compatiblecontent =IE = edge>
< meta name =viewportcontent =width = device-width,initial-scale = 1>
< title> http://stackoverflow.com/q/33628065/315935< / title>
< meta name =authorcontent =Oleg Kiriljuk>
< link rel =stylesheethref =http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/redmond/jquery-ui.css>
< link rel =stylesheethref =http://netdna.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css>
<! - < link rel =stylesheethref =jqGrid / css / ui.jqgrid.css> - >
< link rel =stylesheethref =http://rawgit.com/free-jqgrid/jqGrid/master/css/ui.jqgrid.css>
< style>
html,body {font-size:75%; }
< / style>
< script src =http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js>< / script>
< script src =http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js>< / script>

< script src =http://malsup.github.io/jquery.form.js>< / script>

< script>
$ .jgrid = $ .jgrid || {};
$ .jgrid.no_legacy_api = true;
$ .jgrid.useJSON = true;
< / script>
<! - < script src =jqGrid / js / jquery.jqGrid.src.js>< / script> - >
< script src =http://rawgit.com/free-jqgrid/jqGrid/master/js/jquery.jqgrid.src.js>< / script>
< script>
//<![CDATA [
/ * global $ * /
/ * jslint browser:true * /
$(function(){
use strict;
/ * global $ * /
/ * jslint plusplus:true,browser:true,eqeq:true * /
$(function(){
use strict ;
var mydata = [
{id:10,_image_Pilt:null,invdate:2013-11-01,name:',note:note,amount: 200.00,税金:10.00,关闭:true,ship_via:TN,总计:210.00}
],
editSettings = {


url:null,
useDataProxy:true,
dataProxy:function(opt,args){dataProxyAjax(opt,args,'Artpilt');},


checkOnUpdate:true,
reloadAfterSubmit:false,
closeOnEscape:true,
savekey:[true,13],
closeAfter编辑:true

addSettings = {
checkOnUpdate:true,
reloadAfterSubmit:false,
savekey:[true,13],
closeOnEscape: true,
closeAfterAdd:true

delSettings = {
},
initDateEdit = function(elem){
setTimeout(function(){
$(elem).datepicker(
dateFormat:dd-M-yy,
showOn:button,
changeYear:true,
changeMonth:true ,
showButtonPanel:true,
showWeek:true
});
},50);

initDateSearch = function(elem){
setTimeout(function(){
$(elem).datepicker({
dateFormat:dd-M- yy,
changeYear:true,
changeMonth:true,
showButtonPanel:true,
showWeek:true
});
},50);
},
removeTheOptionAll =函数(elem){
},
dataProxyAjax =函数(opts,act,entity){
//opts.url = $ grid .jqGrid('getGridParam','url');
if(opts.data._oper ===edit){
opts.url ='http://httpbin.org/status/200';
}
else {
opts.url ='http://httpbin.org/status/201';
}
opts.iframe = true;
var $ form = $('#FrmGrid_'+ $ grid.jqGrid('getGridParam','id')),
ele;

//当没有文件上传时使用正常的ajax-call
// if($ form.find(':file [value!=]')。size()= = 0){
// $ .ajax(opts);
// return;
//

//防止非文件输入双重序列化$ b $ ele = $ form.find('INPUT,TEXTAREA,SELECT')。not(':file' );
ele.each(function(){
$(this).data('name',$(this).attr('name'));
$(this).removeAttr ('name');
});

//只发送以前生成的数据+文件
$ form.ajaxSubmit(opts);
//在表单提交后重新设置名称
setTimeout(function(){
ele.each(function(){
$(this).attr('name', $(this).data('name'));
});
},200);
},

$ grid = $(#list)
;
$ b $(#list)。jqGrid({
useDataproxy:true,
dataProxy:function(opt,args){dataProxyAjax(opt,args,'Artpilt') ;},

datatype:local,
data:mydata,
colNames:[,Image,Select image,Client,Date ,金额,税,合计,关闭,通过发货,注释],
colModel:[
{name:act,template: },


{label:Pilt,name:_image_Pilt,edittype:image,editoptions:{
src:
,editable:true,formatter:function(cell,options,row){
return'< img src = \https:// placehold。 it / 100x100 \/>';
}
,search:false,title:,width:54
},{edittype file,label:,name:Pilt,search:false,title:,width:54,hidden:true,editrules edithidden:true},e ditable:true},

{name:name,width:60,editrules:{required:true}},
{name:invdate,width:80,align :格式选项:{newformat:dMY,reformatAfterEdit:true},
editoptions:{dataInit:initDateEdit,size:14}:center,sorttype:date,
formatter: ,
searchoptions:{dataInit:initDateSearch}},


{
name:amount,width:62,template:number,
格式化程序:number,formatoptions:{decimalSeparator:,,thousandsSeparator:,decimalPlaces:2,defaultValue:'0,00'},
editoptions:{
maxlength:7,
类型:数字,
最多:9999,
dataEvents:[
{
类型:blur,
fn:function(e){
if(e.target.checkValidity()){
$(e.target).removeClass UI-状态误差);
} else {
$(e.target).addClass(ui-state-error);
alert(e.target.validationMessage);
$(e.target).focus();
}
}
}
]
}
},


// {name:amount ,width:70,formatter:number,align:right},



{name:tax,width:50,formatter:number ,align:right},
{name:total,width:60,formatter:number,align:right},
{name:closed 70,align:center,formatter:checkbox,
edittype:checkbox,editoptions:{value:Yes:No,defaultValue:Yes},
stype:select ,
searchoptions:{
sopt:[eq,ne],
value::All; true:Yes; false:No,
dataInit:removeTheOptionAll
}},
{name:ship_via,width:100,align:center,formatter:select,
edittype:select,editoptions:值:FE:FedEx; TN:TNT; IN:Intim,defaultValue:TN},
stype:select,
searchoptions:{
sopt:[eq ,ne],
value::All; FE:FedEx; TN:TNT; IN:Intim,
dataInit:removeTheOptionAll
}},
{name: note,width:60,sortable:false,edittype:textarea}
],
cmTemplate:{editable:true,searchoptions:{clearSearch:false}},
rowNum: 10,
rowList:[5,10,20],
pager:true,
gridview:true,
rownumbers:true,
a utoencode:true,
ignoreCase:true,
sortname:invdate,
viewrecords:true,
sortorder:desc,
说明:本地表单编辑,
height:100%,
editurl:http://httpbin.org/status/200,
// editurl:clientArray,
$ multiSearch:true,
overlay:false,$ b $ onClose:function(){$ b $($ b})。jqGrid(navGrid,{},editSettings,addSettings,delSettings, b //如果我们在datapicker打开时关闭搜索对话框
// datepicker将保持打开状态。为了解决这个问题,我们必须隐藏
// datepicker使用的div
$(div#ui-datepicker-div.ui-datepicker)。hide();
}
})。jqGrid(filterToolbar,{defaultSearch:cn});
});
});
//]]>
< / script>
< / head>
< body>
< div id =outerDivstyle =margin:5px;>
< table id =list>< / table>
< / div>
< / body>
< / html>


解决方案您可以使用 useDataproxy code>选项。因此jqGrid根本不发送任何数据。如果在 dataProxyAjax 或者 jquery.form.js 的代码中存在一些问题。 jqGrid只准备 postdata 对象中的数据。该对象只包含一个属性,其中 Pilt 名称。因此,任何与重复的表单键的帖子的问题可能不是免费的jqGrid中的错误。



如果你想要免费的jqGrid使用输出字符相同的编码,那么你只需要包含 autoEncodeOnEdit:true jqGrid选项。此外,您可以使用 serializeEditData 任何自定义编码。



更新:问题在于使用 jQuery.val()填充添加/编辑窗体的所有字段。引入了这些更改,以支持使用新类型值( number color ,<$ c $)的HTML5输入元素c>范围等等)。由于副作用,jqGrid填充了类型为 image file 的字段。这是报告问题的根源。

这个问题应该在发布提交


In latest free from from github posting images from form edit sends image key two times.

For example using testcase below post data contains:

------WebKitFormBoundaryHjeY1fJPAaaXE56n
Content-Disposition: form-data; name="Pilt"; filename="eeva.bmp"
Content-Type: image/bmp


------WebKitFormBoundaryHjeY1fJPAaaXE56n
Content-Disposition: form-data; name="_image_Pilt"


------WebKitFormBoundaryHjeY1fJPAaaXE56n
Content-Disposition: form-data; name="Pilt"

Note that name="Pilt" appears in tow times.

To reproduce, open code below in Chrome, select row, start form edit, select some image, active chrome developer tools and press submit button. Request payload shows that duplicate Pilt keys are posted.

How to fix this so that there are no duplicate keys on post like in earlier version ?

Testcase:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>http://stackoverflow.com/q/33628065/315935</title>
    <meta name="author" content="Oleg Kiriljuk">
    <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/redmond/jquery-ui.css">
    <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
    <!--<link rel="stylesheet" href="jqGrid/css/ui.jqgrid.css">-->
    <link rel="stylesheet" href="http://rawgit.com/free-jqgrid/jqGrid/master/css/ui.jqgrid.css">
    <style>
        html, body { font-size: 75%; }
    </style>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>

    <script src="http://malsup.github.io/jquery.form.js"></script>

    <script>
        $.jgrid = $.jgrid || {};
        $.jgrid.no_legacy_api = true;
        $.jgrid.useJSON = true;
    </script>
    <!--<script src="jqGrid/js/jquery.jqGrid.src.js"></script>-->
    <script src="http://rawgit.com/free-jqgrid/jqGrid/master/js/jquery.jqgrid.src.js"></script>
    <script>
    //<![CDATA[
    /*global $ */
    /*jslint browser: true */
    $(function () {
        "use strict";
        /*global $ */
        /*jslint plusplus: true, browser: true, eqeq: true */
        $(function () {
            "use strict";
            var mydata = [
                    { id: "10", _image_Pilt: null, invdate: "2013-11-01", name: "'", note: "note", amount: "200.00", tax: "10.00", closed: true, ship_via: "TN", total: "210.00" }
                ],
                editSettings = {


                    url: null,
                    useDataProxy: true,
                    dataProxy: function (opt, args) { dataProxyAjax(opt, args, 'Artpilt'); },


                    checkOnUpdate: true,
                    reloadAfterSubmit: false,
                    closeOnEscape: true,
                    savekey: [true, 13],
                    closeAfterEdit: true
                },
                addSettings = {
                    checkOnUpdate: true,
                    reloadAfterSubmit: false,
                    savekey: [true, 13],
                    closeOnEscape: true,
                    closeAfterAdd: true
                },
                delSettings = {
                },
                initDateEdit = function (elem) {
                    setTimeout(function () {
                        $(elem).datepicker({
                            dateFormat: "dd-M-yy",
                            showOn: "button",
                            changeYear: true,
                            changeMonth: true,
                            showButtonPanel: true,
                            showWeek: true
                        });
                    }, 50);
                },
                initDateSearch = function (elem) {
                    setTimeout(function () {
                        $(elem).datepicker({
                            dateFormat: "dd-M-yy",
                            changeYear: true,
                            changeMonth: true,
                            showButtonPanel: true,
                            showWeek: true
                        });
                    }, 50);
                },
                removeTheOptionAll = function (elem) {
                },
            dataProxyAjax = function (opts, act, entity) {
                //opts.url = $grid.jqGrid('getGridParam', 'url');
                if (opts.data._oper === "edit") {
                    opts.url = 'http://httpbin.org/status/200';
                }
                else {
                    opts.url = 'http://httpbin.org/status/201';
                }
                opts.iframe = true;
                var $form = $('#FrmGrid_' + $grid.jqGrid('getGridParam', 'id')),
                    ele;

                //use normal ajax-call when no files to upload
                //    if ($form.find(':file[value!=""]').size() == 0) {
                //        $.ajax(opts);
                //        return;
                //    }

                //Prevent non-file inputs double serialization
                ele = $form.find('INPUT,TEXTAREA,SELECT').not(':file');
                ele.each(function () {
                    $(this).data('name', $(this).attr('name'));
                    $(this).removeAttr('name');
                });

                //Send only previously generated data + files
                $form.ajaxSubmit(opts);
                //Set names back after form being submitted
                setTimeout(function () {
                    ele.each(function () {
                        $(this).attr('name', $(this).data('name'));
                    });
                }, 200);
            },

                $grid= $("#list")
                ;

            $("#list").jqGrid({
                useDataproxy: true,
                dataProxy: function (opt, args) { dataProxyAjax(opt, args, 'Artpilt'); },

                datatype: "local",
                data: mydata,
                colNames: ["", "Image","Select image", "Client", "Date", "Amount", "Tax", "Total", "Closed", "Shipped via", "Notes"],
                colModel: [
                    {name: "act", template: "actions"},


{    "label": "Pilt", "name": "_image_Pilt", "edittype": "image", "editoptions": {
        "src": ""
    }, "editable": true, "formatter": function (cell, options, row) {
        return '<img src=\"https://placehold.it/100x100\" />';
    }
, "search": false, "title": "", "width": 54
}, { "edittype": "file", "label": "", "name": "Pilt", "search": false, "title": "", "width": 54, "hidden": true, "editrules": { "edithidden": true }, "editable": true },

                    { name: "name", width: 60, editrules: { required: true } },
                    {name: "invdate", width: 80, align: "center", sorttype: "date",
                        formatter: "date", formatoptions: {newformat: "d-M-Y", reformatAfterEdit: true},
                        editoptions: {dataInit: initDateEdit, size: 14},
                        searchoptions: {dataInit: initDateSearch}},


                    {
                        name: "amount", width: 62, template: "number",
                        formatter: "number", formatoptions: { decimalSeparator: ",", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0,00' },
                            editoptions: {
                                maxlength: 7,
                                type: "number",
                                max: "9999",
                                dataEvents: [
                                    {
                                        type: "blur",
                                        fn: function (e) {
                                                if (e.target.checkValidity()) {
                                                    $(e.target).removeClass("ui-state-error");
                                                } else {
                                                    $(e.target).addClass("ui-state-error");
                                                    alert(e.target.validationMessage);
                                                    $(e.target).focus();
                                                }
                                            }
                                    }
                                ]
                            }
                        },


                    //{ name: "amount", width: 70, formatter: "number", align: "right" },



                    { name: "tax", width: 50, formatter: "number", align: "right" },
                    {name: "total", width: 60, formatter: "number", align: "right"},
                    {name: "closed", width: 70, align: "center", formatter: "checkbox",
                        edittype: "checkbox", editoptions: {value: "Yes:No", defaultValue: "Yes"},
                        stype: "select",
                        searchoptions: {
                            sopt: ["eq", "ne"],
                            value: ":All;true:Yes;false:No",
                            dataInit: removeTheOptionAll
                        }},
                    {name: "ship_via", width: 100, align: "center", formatter: "select",
                        edittype: "select", editoptions: {value: "FE:FedEx;TN:TNT;IN:Intim", defaultValue: "TN"},
                        stype: "select",
                        searchoptions: {
                            sopt: ["eq", "ne"],
                            value: ":All;FE:FedEx;TN:TNT;IN:Intim",
                            dataInit: removeTheOptionAll
                        }},
                    {name: "note", width: 60, sortable: false, edittype: "textarea"}
                ],
                cmTemplate: {editable: true, searchoptions: {clearSearch: false }},
                rowNum: 10,
                rowList: [5, 10, 20],
                pager: true,
                gridview: true,
                rownumbers: true,
                autoencode: true,
                ignoreCase: true,
                sortname: "invdate",
                viewrecords: true,
                sortorder: "desc",
                caption: "Demonstrates implementating of local form editing",
                height: "100%",
                editurl: "http://httpbin.org/status/200",
                //editurl: "clientArray",
            }).jqGrid("navGrid", {}, editSettings, addSettings, delSettings, {
                multipleSearch: true,
                overlay: false,
                onClose: function () {
                    // 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("filterToolbar", { defaultSearch: "cn" });
        });
    });
    //]]>
    </script>
</head>
<body>
    <div id="outerDiv" style="margin: 5px;">
        <table id="list"></table>
    </div>
</body>
</html>

解决方案

You use useDataproxy option. Thus jqGrid don't send any data at all. If some problems exists than it should be probably in the code of dataProxyAjax or the code of jquery.form.js. jqGrid just prepare the data in postdata object. The object contains only one property with Pilt name. Thus any problems with "duplicate form key post" could be not a bug in free jqGrid.

If you want that free jqGrid use the same encoding of output characters as before, then you need just include autoEncodeOnEdit: true jqGrid option. Moreover you can use any custom encoding by usage of serializeEditData.

UPDATED: The problem was in the usage of jQuery.val() for filling of all fields of Add/Edit form. The changes was introduced to allow support of HTML5 input elements with new type values (number, color, range and so on). As the side effect jqGrid filled the fields which had the type image and file. It was the origin of the reported problem.

The problem should be fixed after posting the commit.

这篇关于免费jqgrid升级后如何修复表单编辑中的重复表单键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆