1

I have a jqGrid Treegrid defined as below:

$('#MyGrid').jqGrid({
    colNames: ['Id','Nome','Nivel','Combo',''],
    colModel: [
        { hidden: true, name: 'Id' },
        { editable: true, name: 'Nome' },
        { hidden: true, name: 'Nivel' },
        { name: 'Combo', editable: true, edittype: 'select',
            editoptions: {
                buildSelect: createSelectList ,
                dataUrl: '/Home/GetCombo' // <-- to this controller, I want
                    // to send the id of the row edited to load custom items
                    // in select object
            }}, 
        { formatter: 'actions', formatoptions: { keys: true },
            resizable: false, search: false, sortable: false,
            width: 60, viewable: false, name: 'actions' }
    ],
    cellEdit: true,
    url: '...',
    datatype: 'json',
    editurl: '...',
    jsonReader: {
        repeatitems: false,
        id: 'Id',
        subgrid: { repeatitems: false }
    }, 
    mtype: 'POST',
    gridComplete: function() { myOnGridComplete(); },
    ajaxSelectOptions: {
        data: {
            tempid: function () {
                // !!! the next line always returns null
                return $('#MyGrid').jqGrid('getGridParam', 'selrow');
            }
        }
    }, 
    prmNames: { npage: 'npage' }, 
    rowNum: -1,
    ExpandColClick: true,
    ExpandColumn: 'Nome',
    treeGrid: true,
    treeGridModel: 'adjacency',
    width: 700,
    height: '100%'
});

My goal is to send the current row ID to the server, but when I use $('#MyGrid').jqGrid('getGridParam', 'selrow') I always get a null value.

I already read this posts but none of them solve my problem:

Any sugestions?

tks in advance!

Update 1:

The TreeGrid bind is ok. The real problem is when I click the Edit Button in the leaf node. In this event, I want to send additional data to the server.

I tried to accomplish this using the ajaxSelectOptions, but this command always returns null: $('#MyGrid').jqGrid('getGridParam', 'selrow')

Workaround

This is a workaround that I did before Oleg's help:

Step 1: Create a hidden field in the HTML

Step 2: In my myOnGridComplete function, I set a click event to the edit button:

function onGridAjusteDTOComplete()
{
    $('#MyGrid').find('span.ui-icon-pencil').each(function() {
        $(this).click(function(){
            var rowID = $(this).parents('tr').attr('id');
            // !!! the next commented line not work in my case
            // $('#MyGrid').jqGrid('setSelection', therowid );
            $('#myHiddenField').val(rowID); // <-- this works
        });
    });
}

Step 3: Get the rowID from the hidden field in the ajaxSelectOptions:

ajaxSelectOptions: "{type: 'GET', contentType: 'application/json; charset=utf-8',dataType: 'json',cache: false, async:false, data: {id: function () { return $('#myHiddenField').val(); }}}"

Solution

See the solution provided by Oleg below. It's just amazing. Thank you Oleg.

Community
  • 1
  • 1
Luiz
  • 198
  • 2
  • 13

1 Answers1

0

I am not sure that I understand your problem correctly. TreeGrid send automatically the id of parent node during loading of children nodes. See the documentation about nodeid, parentid, n_level parameters which will be send to the server. So I don't understand why you could need to send the id of the currently selected row (selrow) additionally to the server.

UPDATED: Now I understand the reason of the problem which you describe. It's really interesting problem which could have other people.

The real solution would be to change the code of jqGrid to support some callback function which could construct the data parameter used in $.ajax call which build <select>. The simplest modification of the original code of jqGrid will be to insert the line

var rowid = $.jgrid.stripPref($t.p.idPrefix,
        String(options.id).substring(0, String(options.id).length - String(options.name).length - 1));

before the line line of code where $.ajax with dataUrl will be called. Additionally one need to add one more parameter in the $.ajax:

data: $.isFunction(ajaxso.postData) ?
    ajaxso.postData.call($t, rowid, String(options.name), vl) :
    ajaxso.postData,

After such changes one will be able to use

ajaxSelectOptions: {
    postData: function (rowid, colName, value) {
        return { id: rowid };
    }
}

The demo demonstrate that the approach work. You could see in Fiddler, Firebug or in Developer Tools that the option id will be really send to the URL. I'll post the corresponding suggestion to trirand later (I want to make some additional improvements for more common case)

If you need to implement the solution with the current version of jqGrid you can do the following instead. You can "subclass" the method $.jgrid.createEl which do the $.ajax request. The implementation will also simple enough:

var originalCreateEl = $.jgrid.createEl,
    createElementOptions;

$.extend($.jgrid, {
    createEl: function (eltype, options, vl, autowidth, ajaxso) {
        if (options.dataUrl) {
            createElementOptions = options;
        }
        return originalCreateEl.call(this,eltype, ptions,vl,autowidth,ajaxso);
    }
});

$('#MyGrid').jqGrid({
    ...
    ajaxSelectOptions: {
        data: {
            id: function () {
                var id = createElementOptions.id,
                    colName = createElementOptions.name;
                if (typeof id !== "string" || typeof colName !== "string") {
                    return null;
                }
                return id.substring(0, id.length - colName.length - 1);
            }
        }
    }
});

The next demo demonstrate the way.

UPDATED 2: I posted the pull request to make support of postData as property of ` andajaxSelectOptions`. The request is committed now (see here). So the next version of jqGrid (higher as 4.4.1) will have the functionality "out of the box".

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Hi Oleg. Tnks for the help. My problem is not to bind the treegrid. this is working ok. My problem is when I click on the Edit button in the leaf node. In this click event, I wanto to send additional data to the server. With this additional info, I can, for example, bind diffenrent information for each combobox in diffenrent row. – Luiz Dec 17 '12 at 12:05
  • @WashingtonMorais: Is the editing row is really selected in your scenario? `selrow` equal to `null` mean that no row is selected. The `formatter: 'actions'` don't prevent selection of rows. Probably the code which you use in `myOnGridComplete` prevent in some way the selection of row during editing? – Oleg Dec 17 '12 at 13:27
  • Hi Oleg. I've found the solution. In myOnGridComplete I set a click event to the Edit and get the row id into a Hidden Field. After, in the ajaxSelectOptions I pass this id to the server. – Luiz Dec 17 '12 at 13:46
  • @WashingtonMorais: Sorry, but I don't understand why you need to do this. Binding `click` event handler to every row just get unnecessary memory resources. You don's answered on my question: "Is the editing row is really selected in your scenario?". If you need to trace the last editing row by action formatter you can use `onEdit` callback (see [here](http://stackoverflow.com/a/5204793/315935) for example). In any way the it's unclear **why** `selrow` is null. It should be null only if no row is selected. – Oleg Dec 17 '12 at 14:07
  • Hi Oleg. I'll try with onEdit. Since I get the test, I'll post the results. Tnks. – Luiz Dec 17 '12 at 14:44
  • 1
    I did the tests and noticed that the call to the URL in the parameter dataUrl happens before the event onEdit. I need to get the rowid before the call to dataURL. – Luiz Dec 17 '12 at 15:30
  • @WashingtonMorais: Now I understand the reason of the problem which you have. The row will be selected, but it will be selected **after** the Ajax request with `ajaxSelectOptions` will be sent. The solution which you suggest is a workaround, but it do too many unneeded work. Especially binding of `click` handler to *every button* seems to me too expensive. The usage of hidden DOM elements is also not needed. Much more easy to declare variable in outer scope. Inside of `beforeSelectRow` callback you can save the id of rows in the variable which you can use inside of `ajaxSelectOptions`. – Oleg Dec 17 '12 at 16:18
  • @WashingtonMorais: I will append my answer with the corresponding code fragment. – Oleg Dec 17 '12 at 16:19
  • @WashingtonMorais: I updated my answer. The way with `beforeSelectRow` also don't work because it will be called too late. By the way one more disadvantage of the solution which you described is *the order* of called `click` handles. If the `click` handler of "actions" formatter would be called before youth then you would set the value for `$('#myHiddenField')` too late. – Oleg Dec 17 '12 at 19:32
  • You're a genius!!! It worked perfectly. It's interesting how this feature did not exist before in jqGrid. Your solution is very simple and clean. Thank you! – Luiz Dec 18 '12 at 10:45
  • @WashingtonMorais: You are welcome! I will prepare my suggestions and will post there to trirand. I think it could interesting for many other users of jqGrid. What I want to add to the suggestions described in my answer is the possibility to define `postData` callback inside of `editoptions` or `searchoptions`. In the way one will don't need to have one *common* `ajaxSelectOptions.postData` for all columns of jqGrid. I think it would be easier for the usage. – Oleg Dec 18 '12 at 10:57
  • @WashingtonMorais: I want only inform you (see "**UPDATED 2**" part of my answer) that the corresponding changes in the main code of jqGrid is now on github. – Oleg Jan 08 '13 at 09:05