free-jqgrid / jqGrid

jQuery grid plugin
https://github.com/free-jqgrid/jqGrid
Other
479 stars 195 forks source link

inline editing Select Dropdwon Option returning the option text instead of option value #423

Open boulepick opened 6 years ago

boulepick commented 6 years ago

Good day all,

I think there is an issue with colModel editoptions formatter select type, from the code below i'm dynamically creating my select dropdown whenever the user is doing in inlinde editing. Building and displaying the select is working fine when the user is in inline editing mode. howerver with the option "formatter: 'select'", when saving the inline editing the column of the dropdown goes back to a blank cell, whatever the user had selected disappears. if i change the "formatter: 'select'" to "formatter: 'custom'" the field will not go back to a blank cell but when retrieving the rowData i'm getting the text of the select option and not the value.

i want the user to be able to update the table rows and then click on a button to send all of the table rows data via an ajax call. sort of a batch update.

const editSelectedRow= function (rowid, iRow, iCol, e) {
    const $self = $(this);
    $self.jqGrid('editRow', rowid, {
        keys: true,
        focusField: e.target,
    });
};

url: urlGetGridData,
editurl: 'clientArray',
postData: gridPostData,
idPrefix: 'n_',
colNames: planColName,
caption: plantGridCaption,
pager: planGridPager,
height: defaultHeight,
colModel: [
    {
        name: 'quantity',
        width: 35,
        align: 'center',
        editable: true,
        editoptions: {
            dataInit(elem) {
                $(elem).addClass('inline-edit-cell form-control input-xs');
            },
        },
        editrules: {
            required: true,
        },
    },
    {
        name: 'ID',
        width: 90,
        align: 'left',
        editable: true,
        edittype: 'select',
        _formatter: 'select_',
        editoptions: {
            dataUrl: urlGetIDs,
            postData(rowid) {
                const id = $(this).getCell(rowid, 'otherID');
                return { id };
            },
            dataInit(elem) {
                $(elem).addClass('inline-edit-cell form-control input-xs');
            },
            buildSelect(response) {
                const drpData = typeof response === 'string' ? $.parseJSON(response.responseText) : response;
                let s = '<select>';
                $.each(drpData, function () {
                    s += `<option value="${this.itemID}">${this.a} ${this.d} (${this.g})</option>`;
                });
                return `${s}</select>`;
            },
        },
        editrules: {
            required: true,
        },
    },

],
ondblClickRow: editSelectedRow,
subGrid: false,
footerrow: true,
userDataOnFooter: true,
ajaxSelectOptions: { type: 'POST', dataType: 'JSON' },
OlegKi commented 6 years ago

Please post always the version of free jqGrid, which you use and the test data. The test data returned from urlGetIDs and urlGetGridData are required too. Which datatype you use in the grid? ("xml", "json", ...). It's strictly recommended to provide the demo, which reproduces the problem if you post the issue.

The code, which you post contains very strange symbols (see `` inside of the code ofbuildSelect`).

s += `<option value="${this.itemID}">${this.a} ${this.d} (${this.g})</option>`;
...
return `${s}</select>`;

Which quote symbol you use in your original code? In any way the code of buildSelect looks incorrect because you use Angular syntax constructs with JavaScript statements.

boulepick commented 6 years ago

Hi OlegKi,

i'm using Free-jQGrid version 4.15.3 (https://cdn.jsdelivr.net/npm/free-jqgrid@4.15.3/js/jquery.jqgrid.src.min.js)

I actually did not specify the datatype in the colModel but in the ajaxSelectOptions (Json)

data from urlGetIDs is in the format

[
        {
            "itemID":"01002-1138",
            "n":1002,
            "s":1,
            "a":1,
            "g":3.8,
            "d":"round circle"
        },
        {
            "itemID":"01002-2194",
            "nutrientID":1002,
            "s":2,
            "a":1,
            "g":9.4,
            "d":"round"
        },
        {
            "itemID":"01002-31151",
            "nutrientID":1002,
            "s":3,
            "a":1,
            "g":151,
            "d":"circle"
        },
        {
            "itemID":"01002-4176",
            "nutrientID":1002,
            "s":4,
            "a":1,
            "g":76,
            "d":"stick"
        }
    ]

data from urlGetGridData is in the format:

{
    "page":1,
    "total":1,
    "records":2,
    "rows":[
        {
        "quantity":10,
        "ID":"01002-2194"
        },
        {
        "quantity":6,
        "ID":"07403-4528"
        }
    ]
}

as for the buildselect, i was using the new ES6 syntax for concatenation but can be changed to s += '<option value="' + this.itemID + '">' + this.a + ' ' + this.d + ' ' + this.g + '</option>';

Cheers

boulepick commented 6 years ago

Well it does not seem that jqGrid is too friednly with select dropdowns, so for now i created this workaround using data event to save the option value and other additional data to hidden columns that can be sent via an ajax call. so everytime the user selects a different dropdown, the values are passed to the hidden fields before the user save the row.

editoptions: {
        dataUrl: urlGetIDs,
        postData(rowid) {
                const id = $(this).getCell(rowid, 'otherID');
                return { id };
        },
        dataInit(elem) {
                $(elem).addClass('inline-edit-cell form-control input-xs');
        },
        buildSelect(response) {
                const drpData = typeof response === 'string' ? $.parseJSON(response.responseText) : response;
                let s = '<select>';
                $.each(drpData, function () {
                        s += `<option value="${this.itemID}">${this.a} ${this.d} (${this.g})</option>`;
                });
                return `${s}</select>`;
        },
        dataEvents: [
            {
                type: 'change',
                fn: function (e) {
                    const selectID = this.id;

                    // get some addtional data that was passed to the select option using jquery
                    const optionData = $('#' + selectID + ' option[value="' + this.value + '"]').attr('data-moreData');

                    // get the current rowID
                    const rowid = e.data.rowId;

                    // get the value of the selected option
                    const selOptionValue = this.value;

                    // save the information to the hidden cells for when submitting all to ajax
                    $grid.jqGrid('setCell', rowid, 'hiddenID', selOptionValue);
                    $grid.jqGrid('setCell', rowid, 'hiddenData', optionData);
                },
            }
        ]
}
OlegKi commented 6 years ago

It seems to me that there are exist misunderstanding what formatter: 'select' do.

Without usage of formatter: 'select' you should build select with the same values and texts for all options. In the same way, the input of the grid should contains the texts instead of values.

If you do want to use formatter: 'select' then the input data could be stay unchanged, but you have to set formatoptions.value of ID column before jqGrid process the server response. It allows formatter: 'select' to uses the data and to display the texts instead of the values included in the input. I suggest you to use beforeProcessing for that. See the old answer or another one. In your case the code could be about the following: https://jsfiddle.net/enwz51sp/88/