【问题标题】:How to send the data to the server after inline editing?内联编辑后如何将数据发送到服务器?
【发布时间】:2018-06-14 07:24:21
【问题描述】:

我正在使用 jQgrid Free (release 4.15.2),我需要添加内联编辑行的功能,这根本不是问题,因为它很容易设置。这是我正在使用的代码:

$.jgrid = $.jgrid || {};
$.jgrid.no_legacy_api = true;
$.jgrid.useJSON = true;

$(function () {
    "use strict";

    var $grid = $("#list"),
        pagerSelector = "#pager",
        customAddButton = function (options) {
            $grid.jqGrid('navButtonAdd', pagerSelector, options);
            $grid.jqGrid('navButtonAdd', '#' + $grid[0].id + "_toppager", options);
        };

    $.fn.fmatter.customActionsFormatter = function (cellValue, options, rowData) {
        return '<a href="#" title="Delete selected row"><span class="fa fa-fw fa-trash-o delete_row" data-id="' + rowData.Id + '"></span></a>';
    };

    $grid.jqGrid({
        url: '/ajax/plans_to_forms/get_all',
        datatype: "json",
        colNames: ["", "Id", "Form #", "Form", "Plan", "Class", "Drug"],
        colModel: [
            {name: "act", formatter: "customActionsFormatter", width: 20, search: false},
            {name: "Id", jsonmap: "Id", key: true, hidden: true},
            {name: "FormId", align: 'center', fixed: true, frozen: true, resizable: false, width: 100},
            {name: "FormName", width: 300},
            {name: "PlanName", width: 300},
            {name: "DrugGroupName", width: 300},
            {name: "DrugName", width: 300}
        ],
        cmTemplate: {autoResizable: true, editable: true},
        iconSet: "fontAwesome",
        rowNum: 25,
        guiStyle: "bootstrap",
        autoResizing: {compact: true},
        rowList: [25, 50, 100, "10000:All"],
        viewrecords: true,
        autoencode: true,
        sortable: true,
        pager: pagerSelector,
        toppager: true,
        cloneToTop: true,
        hoverrows: true,
        multiselect: true,
        multiPageSelection: true,
        rownumbers: true,
        sortname: "Id",
        sortorder: "desc",
        loadonce: true,
        autowidth: true,
        autoresizeOnLoad: true,
        forceClientSorting: true,
        shrinkToFit: true,
        navOptions: {
            edit: false,
            add: false,
            del: false,
            search: false
        },
        inlineEditing: {keys: true, defaultFocusField: "DrugGroupName", focusField: "DrugGroupName"},
        onSelectRow: function (rowid, status, e) {
            var $self = $(this), savedRow = $self.jqGrid("getGridParam", "savedRow");

            if (savedRow.length > 0 && savedRow[0].id !== rowid) {
                $self.jqGrid("restoreRow", savedRow[0].id);
            }

            $self.jqGrid("editRow", rowid, {focusField: e.target});
        }
    }).jqGrid('navGrid', pagerSelector, {
        search: false,
        edit: false,
        add: false,
        del: false,
        refresh: true,
        cloneToTop: true
    }).jqGrid("filterToolbar", {
        stringResult: true, searchOnEnter: false, defaultSearch: 'cn'
    }).jqGrid("gridResize").jqGrid('setFrozenColumns');

    customAddButton({
        caption: 'Delete selected',
        buttonicon: 'fa-trash-o',
        title: "Delete all selected rows",
        onClickButton: function () {
            var rowIds = $("#list").jqGrid('getGridParam', 'selarrrow');

            if (rowIds.length > 0) {
                delete_all_link_modal.modal();
                delete_all_link_modal.attr('data-link-ids', rowIds);
            } else {
                alert('You must select at least one item.');
            }
        }
    });
});

以下行启用内联编辑:

inlineEditing: {keys: true, defaultFocusField: "DrugGroupName", focusField: "DrugGroupName"}

我的问题在哪里?我只需要编辑DrugGroupName 列,上面的行使整行可编辑,这导致我提出以下问题:

  • 是否可以只编辑一组给定的列而不是全部? - 我正在检查文档here,但找不到任何有用的东西

  • 是否可以在我单击任何其他位置或按 ENTER 键时立即将数据发送到服务器? - 我想避免额外点击保存图标。

更新:我已经找到了第一个问题的答案。我只需要在定义colModel 时使该列不可编辑。例如:

colModel: [
    {name: "act", formatter: "customActionsFormatter", width: 20, search: false},
    {name: "Id", jsonmap: "Id", key: true, hidden: true},
    {name: "FormId", align: 'center', fixed: true, frozen: true, resizable: false, width: 100, editable: false},
    {name: "FormName", width: 300, editable: false},
    {name: "PlanName", width: 300, editable: false},
    {
        name: "DrugGroupName",
        width: 300,
        edittype: "select",
        editoptions: {
            generateValue: true,
            selectFilled: function (options) {
                setTimeout(function () {
                    $(options.elem).select2({
                        width: "100%"
                    });
                }, 0);
            }
        },
        stype: "select", searchoptions: {
            sopt: ["eq", "ne"],
            generateValue: true,
            noFilterText: "Any",
            selectFilled: function (options) {
                $(options.elem).select2({
                    width: "100%"
                });
            }
        }
    },
    {name: "DrugName", width: 300, editable: false}
]

这样我就强制 DrugGroupName 成为唯一可编辑的。

【问题讨论】:

  • 免费 jqGrid 允许将editable 不仅用作布尔值,还可以用作"hidden"、"disabled"、"readonly" 或回调函数。您可以在例如"FormId" 列中使用editable: "hidden" 来发送列中的数据,但不能编辑"FormId" 列中的数据。此外,您可以删除不需要的 {name: "Id", jsonmap: "Id", key: true, hidden: true} 列并添加 prmNames: { id: "Id" }。它修复了填充网格和编辑:内联编辑将在编辑期间发送Id 属性而不是id。
  • @Oleg 我知道你的时间很宝贵,但你能以上面的解释为例发布答案吗?另外关于“将数据发送到服务器”,我找到了this 和this,但我仍然不清楚如何实现这一点,您能否将其也添加到答案中?
  • 我可以稍后再做。你能用一些简单的测试数据准备 jsfiddle 演示,你的代码?您可以使用 jsfiddle 的 Echo 服务来模拟从服务器加载数据。您究竟想将哪些数据发送到服务器?来自编辑行的其他列或其他动态值?我在您的网格中没有看到任何 editurl 参数,这很奇怪。您希望 jqGrid 将编辑数据发送到服务器,但您必须指定数据应发送到的 URL (editurl)。您可以在演示中使用 Echo 服务 (editurl: "/echo/json/") 在 DevTools 中进行测试。
  • @Oleg 我不太擅长 JSFiddle,但我为您准备了一个“演示”here。我没有添加远程支持,因为我不知道该怎么做,并且由于某种原因,Bootstrap 模态与 UX 搞混了,不知道为什么。我刚刚发现editurl,所以我已将其添加到演示中,如果您需要我提供其他任何内容,请告诉我。
  • 您在实际项目中使用哪个版本的 Bootstrap、jQuery 和 jQuery UI?你使用 jQuery UI 还是只使用 Bootstrap?另外我不明白customActionsFormatter 的目标。你能解释一下你试图用它来实现什么吗?为什么不使用标准的formatter: "actions"?

标签: javascript jquery jqgrid free-jqgrid


【解决方案1】:

我认为你的代码有很多小问题。我准备了demohttps://jsfiddle.net/OlegKi/rmo2370r/19/,它应该解决了大部分问题,并演示了select2的用法和free jqGrid的一些功能。

第一个小问题是正确 rowid 的使用。您使用当前隐藏的列

{name: "Id", jsonmap: "Id", key: true, hidden: true}

这是对使用 jqGrid 的用户的典型误解。 Rowid 将保存为行的id 属性(&lt;tr&gt; 元素)。见the picture。不需要将案例信息作为隐藏的&lt;td&gt; 元素放置在网格内。而不是那个可以只使用以下 jqGrid 选项

prmNames: { id: "Id" },
jsonReader: { id: "Id" },

相反。选项jsonReader.id 通知jqGrid 在填充网格期间从哪里获取rowid,prmNames.id 在编辑网格期间提供id 的名称。

要在 JSFiddle 中填充 jqGrid,可以使用 Echo 服务:

url: '/echo/json/',
datatype: 'json',
mtype: 'POST', // required for '/echo/json/'
postData: {
    json: JSON.stringify(mydata)
},

对 URL /echo/json/ 的请求将 mydata 作为响应。可以使用 Chrome/IE/Firefox 开发者工具的 Network 选项卡详细检查 HTTP 流量。

以同样的方式使用

editurl: '/echo/json/',
formDeleting: {
    url: '/echo/json/',
    ...
}

用于内联编辑和表单删除。

接下来的变化。我在autoResizing 中添加了resetWidthOrg: true 属性:

autoResizing: {
    compact: true,
    resetWidthOrg: true
}

这改变了autowidth: true 与autoresizeOnLoad: true 结合使用的结果。您可以看到所有列的宽度都基于列的内容比以前更好。详情请见the issues。

我不明白customActionsFormatter 的目标。我将其替换为标准格式化程序操作

{ name: "act", template: "actions" }

如果需要,免费的 jqGrid 允许非常容易地自定义操作按钮。请参阅the answer 和the wiki article 了解更多详情。

你使用的旧代码

cmTemplate: {
  autoResizable: true,
  editable: true
}

并在大多数列中设置editable: false。取而代之的是,您只需从cmTemplate 中删除editable: true,仅在需要编辑的一列中添加editable: true,并在cmTemplate 中包含colModel 中最常用的其他设置:

cmTemplate: {
    width: 300,
    autoResizable: true
}

也可以简化许多其他代码。以onSelectRow的修改代码为例。

要自定义删除对话框,可以使用以下设置:

formDeleting: {
    url: '/echo/json/', // '/ajax/plans_to_forms/delete/' in final solution
    width: 320,
    caption: 'Delete Plan to Form Link',
    msg: 'Are you sure you want to delete this link?',
    beforeShowForm: function ($form) {
        var rowids = $form.find("#DelData>td").data("rowids");
            console.log(rowids);
            if (rowids.length > 1) {
            $form.find("td.delmsg")
                    .html('Are you sure you want to delete all the selected form links?');
            }
    }
}

删除将数据Id=20622,20626和oper=del发送到服务器(formDeleting.url)。如果需要,可以使用serializeDelData 将数据转换为 JSON。

要在编辑期间将更多数据从列发送到服务器,可以在某些列中添加editable: "hidden"。我在演示的FormId 列中添加了属性,并且在编辑期间发送到服务器的数据看起来像

{"FormId":"3393","DrugGroupName":"Some other value","oper":"edit","Id":"20620"}

要填写&lt;select&gt; 的数据,以向服务器发送额外的Ajax 请求,需要使用editoptions.dataUrl。我在演示中添加了editoptions.postData,仅模拟对服务器的真实请求:

editoptions: {
    dataUrl: "/echo/json/",
    postData: {
        json: JSON.stringify([
                "Non-Specialty Medications",
                "General Pharmacy Authorization",
                "Some other value"
            ])
        },
        buildSelect: function (data) {
            var select = "<select>", i;

            for (i = 0; i < data.length; i++) {
                select += "<option value='" + String(data[i]).replace(/\'/g, "&#39;") +
                            "'>" + $.jgrid.htmlEncode(data[i]) + "</option>"
            }
            return select + "</select>";
        },
        selectFilled: function(options) {
            var $self = $(this);

            setTimeout(function() {
                $(options.elem).select2({
                    width: "100%"
                }).on('select2:select', function (e) { 
                    // save the data on selection
                    $self.jqGrid("saveRow", options.rowid);
                });
            }, 0);
        }
    },
    stype: "select",
    searchoptions: {
        sopt: ["eq", "ne"],
        generateValue: true,
        noFilterText: "Any",
        selectFilled: function(options) {
            $(options.elem).select2({
                width: "100%"
            });
        }
    }
}

上述对dataUrl的请求返回JSON字符串[ "Non-Specialty Medications", "General Pharmacy Authorization", "Some other value" ],buildSelect将数据转换为HTML片段,&lt;select&gt;包含所有&lt;options&gt;。生成的 &lt;select&gt; 将在 selectFilled 回调中转换为 select2 控件。最后代码使用

ajaxSelectOptions: {
    type: "POST",
    dataType: "json"
}

将Ajax请求的参数更改为dataUrl的选项。演示 https://jsfiddle.net/OlegKi/rmo2370r/19/ 包含一些其他小的更改,例如删除不需要的空寻呼机 div 和 pager: true 的使用方式,就像您已经使用 toppager: true 一样。这是我在免费的 jqGrid fork 中实现的另一个功能,以简化 jqGrid 的使用。

【讨论】:

  • 我想在编辑操作成功后显示一条消息,这意味着我从后端返回 1 作为 JSON,我应该为此使用什么回调?
  • @ReynierPM:jqGrid 将编辑解释为成功,对应请求的 HTTP 状态码成功(aftersavefunc 回调 (inlineEditing.aftersavefunc) 作为最终消息。如果编辑失败,您可以使用errorfunc 回调 (inlineEditing.errorfunc) 来“解码”服务器响应并显示错误消息。如果在发生错误时无法返回错误 HTTP 状态,您可以使用 successfunc 回调 (inlineEditing.aftersavefunc) 获取服务器响应作为参数,并在错误时返回 [true] 或 [false, "error text"]。
  • 还有一件事,由于某种原因,我无法拖动删除弹出窗口,并且它显示在浏览器窗口的左侧截断处,是否有任何属性可以将其居中?像align 这样的东西?顺便说一句,这个formDeleting 的文档在哪里?我在 jQgrid Wiki 上找不到它
  • @ReynierPM:例如,可以在formDeleting 中定义静态top: 200 和left: 300 值,或者使用beforeShowForm 或afterShowForm 回调(formDeleting.afterShowForm)来更改动态删除对话框的位置。请参阅the old answer 或another one 作为afterShowForm 的可能代码示例。
  • @ReynierPM:您可以在formDeleting 内指定delGridRow 的任何选项或回调。它简化了使用,因为delGridRow 可以间接调用。我在the wiki article 中描述了这一点。更准确地说,该选项在 TypeScript 中描述为 here 和 here。
猜你喜欢
  • 1970-01-01
  • 2016-08-29
  • 2020-06-17
  • 2019-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多