【问题标题】:Formatter function call twice in jqGrid格式化程序函数在 jqGrid 中调用两次
【发布时间】:2015-09-02 11:31:10
【问题描述】:

我正在尝试在 jqGrid 中使用称为 TransactionNumber 的特殊字段显示数据。此字段是自定义控件,即自定义 html(两个 html 标签 img 和 span)。


要实现的主题/目标

  1. 当交易列有值时,它应该显示金色箭头(img),如果它不包含值,则不应显示金色箭头(img)。
  2. 编辑行后,这个金色箭头 (img) 也应该隐藏起来,因为有一些自定义控件已经有了这个。

我的自定义控件将如下所示。

<img src="../img/link.jpg"/><span>Manual/2839</span>

请看下面的屏幕截图。

经过一番调查,我发现了一些事实。 1. 每行调用两次格式化函数。 2. 第一次尝试 cellvalue 变量未定义,rowobject 不包含实际的行数据。 3. 在第二次尝试中,cellvalue 变量包含实际值,rowobject 包含实际数据。 4.编辑行后,列的值为:

<img onclick="javascript:alert();" src="img/LinkButton_Transperent.png">Manual/1011197

我没想到,我只期待价值而不是形象。 这是正确的行为吗?我认为它应该只调用一次。

请看我下面的sn-p。

 $("#uxStages").jqGrid({
            datatype: 'xmlstring',
            datastr: xmlstring,
            mtype: 'GET',
            pager: '#uxStagesMap',
            ajaxGridOptions: {
                contentType: 'application/json; charset=utf-8'
            },
            xmlReader: {
                repeatitems: false,
                root: "BO>SalesOpportunitiesLines",
                row: 'row'
            },
            colNames: ['..', 'LineNum', 'Start Date', 'Close Date', 'Sales Employee', 'Stage', 'Percentage', 'Potential Amount', 'Document Type', 'DocEntry', 'Doc. No.', 'Owner'],
            colModel: [
                {
                    name: 'act', index: 'act', width: 40, align: 'center', sortable: false, formatter: 'actions',


                    formatoptions: {
                        keys: true, // we want use [Enter] key to save the row and [Esc] to cancel editing.
                        onEdit: function (rowid) {
                            var grid = $("#uxStages");
                            var selectedRowId = grid.jqGrid('getGridParam', 'selrow');
                            lastSelection = selectedRowId;
                            grid.jqGrid('editRow', selectedRowId, true, null, null, null, null, OnSuccessEdit_Stages);
                            $('#' + selectedRowId + "_StageKey").css('width', '100%');
                            $('#' + selectedRowId + "_SalesPerson").css('width', '100%');
                            $('#' + selectedRowId + "_DataOwnershipfield").css('width', '100%');
                            $('#' + selectedRowId + "_DocumentType").css('width', '100%');
                            //$('#' + selectedRowId + "_DocumentNumber").css('width', '100%').css('height', '13.37px').css('padding','2px').css('border','1px');
                            //    $(this).MessageBox('error', 'Cannot Add Stage for Current DocStatus');
                        },
                        onSuccess: function (jqXHR) {
                            return true;
                        },
                        onError: function (rowid, jqXHR, textStatus) {
                            alert("in onError used only for remote editing:" +
                                        "\nresponseText=" + jqXHR.responseText +
                                        "\nstatus=" + jqXHR.status +
                                        "\nstatusText" + jqXHR.statusText +
                                        "\n\nWe don't need return anything");
                        },
                        afterSave: function (rowid) {
                            //debugger;
                            OnSuccessEdit_Stages(rowid, null, null);
                        },
                        afterRestore: function (rowid) {
                            // alert("in afterRestore (Cancel): rowid="+rowid+"\nWe don't need return anything");
                        },
                        delOptions: function (rowid) {
                            //debugger;
                        }

                    }

                },
                {
                    name: 'LineNum', key: true, index: 'LineNum', hidden: true, sortable: false, width: 60
                },
                {
                    name: 'StartDate', key: false, index: 'StartDate', sortable: false, align: "left", width: 75,
                    editable: true,
                    formatter: 'date',
                    formatoptions: {
                        srcformat: 'Ymd',
                        newformat: 'd-m-Y'
                    },
                    formatter: function (cellValue, opts, rawdata, action) {
                        //    debugger;
                        if (action === "edit") {
                            // input data have format "dd-mm-yy" format - "20-03-2015"
                            var input = cellValue.split("-");
                            if (input.length === 3) {
                                return input[0] + "-" + input[1] + "-" + input[2];
                            }
                        } else if (cellValue.length === 8) {
                            // input data have format "yymmdd" format - "20150320"
                            var year = cellValue.substr(0, 4),
							month = cellValue.substr(4, 2),
							day = cellValue.substr(6, 2);
                            return day + "-" + month + "-" + year;
                        }
                        return cellValue;
                        // for empty input for example
                    },
                    editoptions: {
                        dataInit: function (elem) {
                            $(elem).datepicker({
                                dateFormat: 'dd-mm-yy'
                            });
                        }
                    }
                }, {
                    name: 'ClosingDate',
                    key: false,
                    index: 'ClosingDate',
                    sortable: false,
                    align: "left",
                    width: 75,
                    editable: true,
                    formatter: 'date',
                    formatoptions: {
                        srcformat: 'Ymd',
                        newformat: 'd-m-Y'
                    },
                    formatter: function (cellValue, opts, rawdata, action) {
                        if (action === "edit") {
                            // input data have format "dd-mm-yy" format - "20-03-2015"
                            var input = cellValue.split("-");
                            if (input.length === 3) {
                                return input[0] + "-" + input[1] + "-" + input[2];
                            }
                        } else if (cellValue.length === 8) {
                            // input data have format "yymmdd" format - "20150320"
                            var year = cellValue.substr(0, 4),
							month = cellValue.substr(4, 2),
							day = cellValue.substr(6, 2);
                            return day + "-" + month + "-" + year;
                        }
                        return cellValue;
                        // for empty input for example
                    },
                    editoptions: {
                        dataInit: function (elem) {
                            $(elem).datepicker({
                                dateFormat: 'dd-mm-yy'
                            });
                        }
                    }
                }, {
                    name: 'SalesPerson',
                    key: false,
                    index: 'SalesPerson',
                    sortable: false,
                    width: 80,
                    editable: true,
                    edittype: "select",
                    formatter: 'select'
                },
            {
                name: 'StageKey',
                key: false,
                index: 'StageKey',
                hidden: false,
                sortable: false,
                width: 80,
                editable: true,
                edittype: "select",
                formatter: 'select'

            },
            {
                name: 'PercentageRate',
                key: false,
                index: 'PercentageRate',
                sortable: false,
                editable: true,
                width: 60
            }, {
                name: 'MaxLocalTotal',
                key: false,
                index: 'MaxLocalTotal',
                sortable: false,
                width: 100,
                editable: true,
                edittype: "text",
                formatter: 'currency',
                formatoptions: {
                    thousandsSeparator: ','
                }
            },
            {
                name: 'DocumentType', key: false, index: 'DocumentType', sortable: false, width: 60, editable: true,
                edittype: 'select', formatter: 'select',
                editoptions: {
                    value: "bodt_MinusOne:;bodt_Quotation:Sales Quotation;bodt_Order:Sales Order;bodt_DeliveryNote:Deliveries;bodt_Invoice:Sales Invoice;bodt_PurchaseQutation: Purchase Quotation;bodt_PurchaseOrder:Purchase Order;bodt_PurchaseDeliveryNote:Goods Receipt PO;bodt_PurchaseInvoice:Purchase Invoice;"
                }
            },
            {
                name: 'DocumentNumber', key: false, index: 'DocumentNumber', sortable: false, width: 40,
                hidden: false
            },
            {
                name: 'TransactionNumber',
                key: false,
                index: 'TransactionNumber',
                sortable: false,
                editable: true,
                width: 70,
                formatter: function (cellvalue, options, rowObject) {
                    debugger;
                    if (rowObject.hasOwnProperty('LineNum')) {
                        if (cellvalue == null || cellvalue == '')
                            return '';//'<span>'+cellvalue+'</span>';
                        else
                            return '<img src="img/LinkButton_Transperent.png" onclick="javascript:alert();" /><span>' + cellvalue + '</span> ';
                    }
                    else
                        return '<span>' + cellvalue + '</span> ';
                },
                editoptions: {
                     
                    dataInit: function (elem) {
                        $(elem).css('width', '98%')
                        .css('text-align', 'center')
                        .css('padding-left', '1px')
                        .css('padding-right', '1px')
                        .css('padding-top', '2px')
                        .css('padding-bottom', '2px');

                        $(elem).ChooseFromListAndLink({
                            init: function () { },
                            defaultValue: $(elem).val(),
                            LinkImage: 'img/LinkButton_Transperent.png',
                            ChooseFromListImage: 'img/choosefromlist.png',
                            OnLinkClick: function (evt) {
                                alert('Underconstruction');
                            },
                            OnListClick: function (evt) {
                                var selectedRowId = $("#uxStages").jqGrid('getGridParam', 'selrow');
                                OpenRelatedDocument(selectedRowId);
                            },
                            OpenListOnTab: true
                        });
                    }
                }
            }, {
                name: 'DataOwnershipfield', key: false, index: 'DataOwnershipfield', hidden: false, sortable: false, width: 75,
                editable: true, edittype: "select", formatter: 'select'
            }
            ],
            rowNum: 100,
            viewrecords: true,
            gridview: true,
            rownumbers: true,
            height: 130,
            loadonce: true,
            width: 1260,
            ondblClickRow: function (rowid) {
                //var grid = $("#uxStages");
                //var selectedRowId = grid.jqGrid('getGridParam', 'selrow');
                //lastSelection = selectedRowId;
                //grid.jqGrid('editRow', selectedRowId, true, null, null, null, null, OnSuccessEdit_Stages);
                //$('#' + selectedRowId + "_StageKey").css('width', '100%');
                //$('#' + selectedRowId + "_SalesPerson").css('width', '100%');
                //$('#' + selectedRowId + "_DataOwnershipfield").css('width', '100%');
                //$('#' + selectedRowId + "_DocumentType").css('width', '100%');
            },
            loadComplete: function () {

                var stagevalues = GetStagesValues();
                var salesvalues = GetSalesValues();
                // name of sales person 
                var owners = GetDataOwnershipValues();
                //name of employees
                $("#uxStages").setColProp('SalesPerson', {
                    edittype: "select",
                    editoptions: {
                        value: salesvalues
                    }
                });
                //Here i m fetching values in namedvalue pairs
                $("#uxStages").setColProp('StageKey', {
                    edittype: "select",
                    editoptions: {
                        value: stagevalues,
                        dataEvents: [

                                     {
                                         type: 'change',
                                         fn: function (event) {
                                             var selectedRowID = $("#uxStages").jqGrid('getGridParam', 'selrow');
                                             var selectedValue = $(this).val();
                                             $('#uxOOST').each(function () {
                                                 $('option', this).each(function () {
                                                     var id = $(this).val();
                                                     if (id == selectedValue) {
                                                         var val = $(this).attr('TagName');
                                                         $('#uxStages').jqGrid('setCell', selectedRowID, 'PercentageRate', val);
                                                     }
                                                 });
                                             });
                                         }

                                     }

                        ]
                    }
                });
                //Here i m fetching values in namedvalue pairs
                $("#uxStages").setColProp('DataOwnershipfield', {
                    edittype: "select",
                    editoptions: {
                        value: owners
                    }
                });
                //Here i m fetching values in namedvalue pairs
                // debugger;
                var ids = $("#uxStages").jqGrid('getDataIDs');
                for (var i = 0; i < ids.length; i++) {
                    var id = ids[i];
                    var SalesPerson = $('#uxStages').jqGrid('getCell', id, 'SalesPerson');
                    //getting text part of select and expected to get value
                    var StageKey = $('#uxStages').jqGrid('getCell', id, 'StageKey');
                    //getting text part of select and expected to get value
                    var DataOwnershipfield = $('#uxStages').jqGrid('getCell', id, 'DataOwnershipfield');
                    //getting text part of select and expected to get value
                    $("#uxStages").editRow(id, true);

                    $("#" + id + "_SalesPerson").each(function () {
                        $('option', this).each(function () {
                            var code = $(this).val();
                            if (code == SalesPerson) $(this).attr('selected', 'selected');
                        });
                    });
                    $("#" + id + "_StageKey").each(function () {
                        $('option', this).each(function () {
                            var code = $(this).val();
                            if (code == StageKey) $(this).attr('selected', 'selected');
                        });
                    });
                    $("#" + id + "_DataOwnershipfield").each(function () {
                        $('option', this).each(function () {
                            var code = $(this).val();
                            if (code == DataOwnershipfield) $(this).attr('selected', 'selected');
                        });
                    });
                    if (i < ids.length - 1) {

                        $('#' + $.jgrid.jqID(id)).addClass('not-editable-row');
                        $('#' + $.jgrid.jqID(id)).addClass('ui-state-error');
                    }
                    //desable All rows of grid for Won & Lost DocStatus
                    if ($('#Radio2').prop('checked') || ($('#Radio3').prop('checked'))) {
                        for (var i = 0; i < ids.length; i++) {
                            $('#' + $.jgrid.jqID(i), "#uxStages").addClass('not-editable-row');
                            $('#' + $.jgrid.jqID(i), "#uxStages").addClass('ui-state-error');
                        }
                    }
                    $("#uxStages").saveRow(id);
                }
            },
            onSelectRow: function (id) {
                if (id && id !== lastSelection) {
                    var grid = $("#uxStages");
                    $('#uxStages').saveRow(lastSelection);
                }
            }
        }).jqGrid('navGrid', '#uxStagesMap', {
            add: false,
            del: false,
            edit: false,
            remove: false,
            refresh: false,
            searchOnEnter: false,
            search: false
        }, {}, {}, {}, {
            multipleSearch: false
        });

有谁知道它为什么会这样? 还是我缺乏 jqGrid 的知识。

【问题讨论】:

  • 了解您使用哪个版本的 jqGrid 很重要?不同版本的 jqGrid 对自定义格式化程序的参数略有不同。

标签: jquery jqgrid


【解决方案1】:

您使用datatype: 'xmlstring',这是您遇到的许多问题的根源。例如,您在自定义格式化程序内部使用 rowObject.hasOwnProperty('LineNum'),但自定义格式化程序 (rowObject) 的 3-d 参数在输入数据的初始处理上具有不同类型。您将拥有带有 XML 节点的元素,而不是带有 LineNum 属性的对象。稍后加载自定义格式化程序的 3-d 参数将是对象。

这种行为使自定义格式化程序的实现更加复杂。可以在自定义格式化程序中编写两个不同的部分。或者,可以更改 jqGrid 以简化数据处理。主要问题是与以前版本的兼容性。如果有人已经编写了将rawdata (rowObject) 处理为XML 节点的格式化程序,那么在更新新版本的jqGrid 后此类代码将被破坏,可以使用rawdata (rowObject) 的简化形式。由于兼容性问题,我在free jqGrid 中对自定义格式化程序的界面进行了另一次更改。免费 jqGrid 4.9 及更高版本扩展了自定义格式化程序的第二个 (options) 参数 并提供了所需信息。

自定义格式化程序的常用接口是

formatter: function (cellValue, options, rawdata, action) {
     ...
}

rawdata 的格式保持不变,但options.rowData 将包含 always 简单对象和已解析的输入数据。所以你可以安全使用options.rowData.LineNum。即使rawdata 是XML 节点并且rawdata.LineNum 将未定义,options.rowData.LineNum 也会为您提供所需的信息。

顺便说一下,格式化程序也会在编辑结束时被调用。如果编辑后的数据格式与初始输入数据的格式不同,那么您可以测试action 的值"add""edit" 以区分两种情况并防止在不需要时包含image编辑后。

【讨论】:

  • 好的。明白了,但是当我以 jqGrid 格式加载数据时,每行都会调用函数。我不明白为什么它会调用两次,理想情况下它应该只调用一次。需要打两次吗?
  • @Manish:它应该被称为一次。我建议您调试代码。我想第二个调用存在是因为您使用了非常复杂的loadCompletegetCell 的调用遵循取消列中数据的格式。 editRow 的调用也将调用 unformatter,saveRow 调用格式化程序。所有代码都使得填充网格的速度慢得多,它也可能是第二次调用格式化程序的来源。
  • 哦,我明白了,奥列格太好了,再次感谢
【解决方案2】:

这是一个工作示例(请查看最后一列 myCustomData):

grid.jqGrid({
        datatype: "local",
        data: mydata,
        colModel:[
            { label: 'Code', name: 'TransactionCode', width: 10, align:'center', editable:true, formatter : 'integer', sorttype: "float", formatoptions: {thousandsSeparator: ".", defaultValue: '0'}},
            { label: 'Reader Name', name: 'Description', width: 20, editable:true },
            { label: 'Serial Number', name: 'SerialNumber', width: 15, align:'center', editable:true },
            { label: 'Start Transaction', name: 'DateTimeStartTransaction', width: 20,  align:'center', editable:true, formatter : 'date', formatoptions: {srcformat: 'ISO8601Long', newformat:'d/m/Y H:i:s'}  },
            { label: 'End Transaction', name: 'DateTimeEndTransaction', width: 20,  align:'center', editable:true, formatter : 'date', formatoptions: {srcformat: 'ISO8601Long', newformat:'d/m/Y H:i:s'}  },
            { label: 'Additional Information', name: 'Status', width: 20, align:'center', editable:true },
            {
                label: ' ',
                name:'myCustomData',
                width: 7,
                align:'center',
                formatter: function (cellvalue, options, rowObject ) {
                    buttons = '<a href="editinvalid?transactionCode=' + rowObject.TransactionCode + '&dateTimeStartTransaction=' + rowObject.DateTimeStartTransaction + '"><img src="<?=Yii::getAlias('@web') . '/images/edit.png'?>"> </a>';
                    return buttons;
                }
            },
        ],
        viewrecords: true,
        height: "100%",
        width: 1070,
        rowNum: 15,
        pager: '#pager_contacts',
    });

【讨论】:

    猜你喜欢
    • 2014-12-22
    • 2011-10-10
    • 1970-01-01
    • 1970-01-01
    • 2015-12-27
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    相关资源
    最近更新 更多