Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jqGrid - How to set custom editoptions based on *initial* column values?

I am using the open source jqGrid plugin with EF4 and ASP.NET Web Forms. I need to set an input element in an inline-editable grid row based on a column value from the DB. For example, the first row could contain a DDL, the second row could contain a checkbox, etc.

I'm trying to achieve this using the custom_element and custom_values, like so:

$("#grid1").jqGrid({
    url: 'Default.aspx/getGridData',
    datatype: 'json',
    ...
    colModel: [
    ...
    //contains the input type ('select', etc.)
    { name: 'InputType', hidden:true }, 
    ...
    //may contain a string of select options ('<option>Option1</option>'...)
    { 
      name: 'Input', 
      editable:true, 
      edittype:'custom', 
      editoptions:{
         custom_element: /* want cell value from InputType column here */ , 
         custom_value:   /* want cell value from Input column here */ 
      } 
     }, 
    ...
    ]
});

The jqGrid docs say that I can call custom functions to set custom_element and custom_values, but I don't see how I can capture column values and pass them into my custom functions.

For setting custom_values, I did notice Oleg's nice solution using the list: parameter, but that appeared to involve an extra Ajax call. I want to avoid this, as I already have the all data I need from the initial Ajax call for the grid.

In summary, I need to do the following while in inline-edit mode:

  1. dynamically assign an input type from a DB value
  2. dynamically assign input values (for DDL or checkboxes) from a DB string

I am also open to skipping the use of custom_element and custom_values, but then I still face the same problem of dynamically setting the edittype and editoptions:{value:} parameters.

Any ideas on how to do this? Is there a different approach that I should be taking?

UPDATE: Thanks for your efforts to help me out. Per request, here is an abbreviated example of my JSON response:

{"d":[
{"Input":null,"InputType":"select"},
{"Input":"From downtown, proceed west on Interstate 70.", "InputType":"text"}
]}

With this data, I would want to show an empty select in one row, and a populated text field in the next row. Both would be editable inline.

SOLUTION: I have returned to this problem in order to find a solution that does not involve using custom_element and custom_values. Here is my solution (based on the accepted answer below) to changing edittype and editoptions :

loadComplete: function () {
    var rowIds = $("#grid1").jqGrid('getDataIDs');

    $.each(rowIds, function (i, row) {
       var rowData = $("#grid1").getRowData(row);

       if (rowData.InputType == 'select') {
          $("#grid1").jqGrid('restoreRow', row);
                var cm = $("#grid1").jqGrid('getColProp', 'Input');
                cm.edittype = 'select';
                cm.editoptions = { value: "1:A; 2:B; 3:C" };
                $("#grid1").jqGrid('editRow', row);
                cm.edittype = 'text';
                cm.editoptions = null;
       }
   });
}

Nota Bene: One important thing for me was remembering to set the editoptions back to null, after calling editrow. Also, as Oleg mentioned in the comments, avoiding the use of custom elements allows me to implement datepicker inputs without extra trouble. This was important for my app, so I ended up accepting Oleg's answer, but I still upvoted Walter's answer, as well. If this is bad form, I sincerely apologize. I simply wanted to reward the solution that worked best for me.

like image 898
bflow1 Avatar asked Sep 23 '11 23:09

bflow1


2 Answers

If you use incline editing you call editRow method somewhere directly in your code. Inside of the editRow method all options from the colModel, which are related to editing, will be examined and use. So you can change dynamically any options like editable, edittype or editoptions. The answer shows how one can change editable property. In the same way you can change any other properties.

If you want you can set the information about editing type and option inside of loadComplete event handle. It has data parameter which represent the original data sent from the server. So you can extend the data with and other information and set editable, edittype or editoptions for any columns based on the information.

like image 163
Oleg Avatar answered Nov 01 '22 22:11

Oleg


Try this:

1. Define a handler for the grid's onSelectRow event (onSelectRow_handler) .
2. Inside the onSelectRow handler:
2.1. Set a globally scoped variable (lastRow) to the function's id parameter.
2.2. Call jqGrid's editRow() function to put the grid into edit-mode. This will trigger the function that you have defined as your custom_element renderer (myelem).
3. Inside myelem: call jqGrid's getRowData method to get the row data of the row you just selected for edit. From there you can get the value in the ElementType column and do your logic that decides which element to render.

You'll have to tweak my code a bit, as I didn't test it 100% end-to-end. I did verify that everything up to step 3 works. I didn't do any research into how you would code myvalue().

function renderGrid () {

    $("#grid").jqGrid({
        datatype: "local",
        colNames: ['Id', 'ElementType', 'Name' ],
        colModel: [
            { name: 'Id', index: 'Id', key: true, hidden: true },
            { name: 'ElementType', index: 'ElementType', },
            { name: 'FullName', index: 'FullName',
              editable: true, edittype: 'custom', 
              editoptions: { custom_element: myelem, custom_value: myvalue} }],
        viewrecords: true,
        caption: "",
        autowidth: true,
        height: 'auto',
        forceFit: true ,
        onSelectRow: onSelectRow_handler           
    });


}

var lastRow = null;
function onSelectRow_handler(id) {

    if(id && id!==lastRow){            
        lastRow=id;
    }
    // editRow will send grid into edit mode which will trigger
    $("#grid").editRow(id, true);

}

function myelem(value, options) {
    var data = $("#grid").getRowData(lastRow);
    // the elementType column contains a key to
    // indicate what Input Element to render
    var elementType = data.ElementType;

    if (elementType == 'text') {        
        var el = document.createElement("input");
        el.type = "text";
        el.value = value;         
    }
    if (elementType == 'checkbox') {
        // etc
    }

    return el;
}

function myvalue(elem, operation, value) {
    if (operation === 'get') {
        return $(elem).find("input").val();
    } else if (operation === 'set') {
        $('input', elem).val(value);
    }
}
like image 35
Walter Stabosz Avatar answered Nov 01 '22 22:11

Walter Stabosz