Jeff Finn Jeff Finn - 3 months ago 29
Javascript Question

How to have different drop down options for a field in jqgrid when editing a row

Hi I want to be able to display a different set of drop down options to the user depending on if they are creating a new row or editing a previously created one. The list is held on a database and I am using JQ Grid with MVC4.

Specifically I want to limit the choice to one element and enforce a default value through the grid when they are creating a new row. If they are editing a row I want to give them more options.

My original plan was to do this in the controller for the grid in my mvc app, but because JQ Grid loads the list for the drop down before it loads the grid rather than when you select to edit a row this is not possible.

I think that I should be using dataEvents for this but I'm not sure.

{ name: 'CodeListStatusId', index: 'CodeListStatusId', editable: true, edittype: "select", editoptions: { value: getStatusCodes(),
dataEvents: [
{ type: 'change',
fn: function (e) {
var row = $(#CodeListGrid).closest('tr.jqgrow');
var rowId = row.attr('CodeListId');
$("select#" + rowId + "_State", row[0]).value("1 : Draft");

}
}
]
}, formatter: 'select' }

Answer

To get a drop down to load each time you select the edit button, use the dataUrl. This has the advantage that it takes a URL that returns HTML for a select statement. This allowed me to point it to my controller where I could perform some logic to decide which elements from my database to show in the drop down. To pass data to the controller, use ajaxSelectOptions. My drop down became

{ 
    name: 'CodeListStatusId', 
    index: 'CodeListStatusId', 
    editable: true, 
    edittype: "select", 
    editoptions: { 
        value: getStatusCodes(), 
        dataUrl: window.g_baseUrl + 'CodeList/DisplayCodeListStatuses/' 
    }, 
    formatter: 'select' 
}

and the ajaxSelect code was

ajaxSelectOptions:      //use this for combination with dataUrl for formatter:select
{
    data: {
        id: function () {
            var selectedRowId = jQuery('#CodeListGrid').jqGrid('getGridParam', 'selrow');
            if (selectedRowId == null) {
                return 0;
            }
            return selectedRowId;
        }
    }
},

There was a bug that happened when you had selected a row to edit and then immediately after you went to add a new row. The old row id was being passed through for the new row. To stop this, I added the line

$('#CodeListGrid').trigger('reloadGrid');

to the aftersave function of editparams for save.

For anyone who wants a complete picture of it all, here is the code for my grid:

$('#CodeListGrid').jqGrid({
    url: window.g_baseUrl + 'CodeList/CodeList/?ContextId=' + $('#ContextId').val(),
    editurl: window.g_baseUrl + 'CodeList/Save/?ContextId=' + $('#ContextId').val(),
    datatype: 'json',
    mtype: 'GET',
    colNames: ['CodeLIst Id', 'CodeList Name', 'Description', 'Effective Date', 'Expiration Date', 'Last Modified', 'Modified By', 'Status'],
    colModel: [
        { name: 'CodeListId', index: 'CodeListId', editable: true, hidden: true },
        { name: 'Name', index: 'Name', editable: true, edittype: "text", editoptions: { maxlength: 50 }, editrules: { required: true } },
        { name: 'Description', index: 'Description', editable: true, edittype: "text", editoptions: { maxlength: 100 }, editrules: { required: true } },
        {
            name: 'EffectiveDate',
            index: 'EffectiveDate',
            editable: true,
            editoptions: {
                dataInit: function (el) {
                    $(el).datepicker({
                        dateFormat: "dd-mm-yy",
                        changeYear: true,
                        minDate: '+1D',
                        changeMonth: true,
                        showButtonPanel: true,
                        onClose: function () {
                            var currentDate = $('[name="EffectiveDate"]').datepicker("getDate");
                            currentDate.setDate(currentDate.getDate()+1);
                            $('[name="ExpirationDate"]').datepicker("option", "minDate", currentDate);
                        }
                    });
               }
            }
        },
        {
            name: 'ExpirationDate', index: 'ExpirationDate', editable: true, editrules: { required: true }, editoptions: {
                dataInit: function (el) {
                    $(el).datepicker({
                        dateFormat: "dd-mm-yy",
                        changeYear: true,
                        changeMonth: true,
                        minDate: '+2D',
                        showButtonPanel: true
                    });
                }
            }
        },
        {name: 'ModifiedDate', index: 'ModifiedDate'},
        { name: 'ModifiedName', index: 'ModifiedName', editable: true, edittype: "text", editoptions: { maxlength: 50 }, editrules: { required: true } },

        { name: 'CodeListStatusId', index: 'CodeListStatusId', editable: true, edittype: "select", editoptions: { value: getStatusCodes(), dataUrl: window.g_baseUrl + 'CodeList/DisplayCodeListStatuses/' }, formatter: 'select' }
    ],
    pager: '#pager',
    rowNum: 10,
    rowList: [10, 20, 30],
    sortname: 'Name',
    sortorder: 'Asc',
    viewrecords: true,
    gridview: true,
    caption: 'CodeLists',
    height: '100%',
    width: totalWidth,
    ajaxSelectOptions:      //use this for combination with dataUrl for formatter:select
    {
        data: {
            id: function () {
                var selectedRowId = jQuery('#CodeListGrid').jqGrid('getGridParam', 'selrow');
                if (selectedRowId == null) {
                    return 0;
                }
                return selectedRowId;
            }
        }
    },
});

If you want more info, I found this page on the API helpful from Triand.