0

Although this question is similar, it was not helpful in my situation. I have several jqGrids opening in a modal, all with inline editing enabled, keys: true, and a very simple aftersavefunc function defined. However, when the ENTER key is used rather than clicking the save icon, I am not seeing the aftersavefunc event fire. Some of the grids are rather large and use of the KEYBOARD strokes are crucial to save time and improve accuracy. Is this a known issue or is there a way to fool jqGrid into thinking the save icon has been clicked?

Below is my jqGrid definition (BEFORE). Any help would be greatly appreciated.

function hiliteQty(i) {
    console.log('Highlighting received quantity on #' + i);
    $eRow = $('tr#' + i);
    var qtyord = $eRow.find('td.qtyOrd').text();
    var qtyrec = $eRow.find('td.qtyRec').text();
    if ((+qtyord === +qtyrec) && (qtyrec !== null) && (qtyrec !== 'undefined') && (qtyrec !== '')) {
        $eRow.find('td.qtyRec').removeClass('incomplete',100,'linear').addClass('complete',1000,'easeInElastic');
    } else {
        $eRow.find('td.qtyRec').removeClass('complete',100,'linear').addClass('incomplete',1000,'easeInElastic');
    };
}
$(function() {
    var ml_id = '<?=$ml_id;?>', ml_name = '<?=$objML_temp->showMLName();?>', suppno = '<?=$objML_temp->gSupp();?>', projnum = '<?=$objJob_temp->gProjectNumber();?>', job_id = '<?=$objML_temp->gJobID();?>', lastDate, lastSel;
    $('#special_dialog').dialog({
        width:'auto',
        height:'auto',
        resizable:true
    });
    $.extend($.jgrid.defaults,{
        inlineData:{
            ml_id:ml_id,
            project_number:projnum,
            job_id:job_id
        },
        rowNum:1000,
        rowList:[20,50,100,500,1000],
        viewrecords:true,
        sortorder:'asc',
        height:500,
        autowidth:true,
        deepempty:true,
        altRows: true,
        grouping: true,
        groupingView: {
            groupField: ["vendor"],
            groupColumnShow: [true],
            groupText: ["<b>VENDOR: {0}</b>"],
            groupDataSorted: true,
            groupSummary: [false]
        }
    });
    // setup Minor Materials grid
    var mmGrid = $('#orderMMGrid'),
        editingRowId,
        mmEditParam = {
            keys: true,
            oneditfunc: function(id) {
                $('#orderMMGrid_ilsave').removeClass('ui-state-disabled');
                $('#orderMMGrid_ilcancel').removeClass('ui-state-disabled');
                hiliteQty(id);
            },
            afterrestorefunc: function() {
                editingRowId = undefined;
            },
            aftersavefunc: function(id) {
                hiliteQty(id);
            }
        },
        mmAutoCompOpts = {
            source: function(request, response) {
                $.getJSON('/json/json.searchmultiMaterials.php',{term:request.term,type:'m'},function(data) {
                    response(data);
                });
            },
            minLength: 3,
            focus: function(e,ui) {
                $('input:text[name="description"]').val(ui.item.description);
                $('input:text[name="vendor"]').val(ui.item.vendor);
                $('input:text[name="mfgr_partno"]').val(ui.item.mfgr_partno);
            },
            select: function(e,ui) {
                $('input:text[name="description"]').val(ui.item.description);
                $('input:text[name="vendor"]').val(ui.item.vendor);
                $('input:text[name="mfgr_partno"]').val(ui.item.mfgr_partno);
                $('input:text[name="vendor_id"]').val(ui.item.vendor_id);
            }
        },
        mmAddParam = {
            rowID: 'new',
            position:'last'
        };
    mmGrid.jqGrid({
        url: '/json/json.getMinorMaterialsOrder.php?ml_id=' + ml_id,
        datatype:'json',
        emptyrecords: 'No Minor Materials on this order',
        colNames: ['ID','Type','Supp','VID','Vendor','PO#','MasTec Part#','Manufacturer Part#','Description','Ship Date','Qty Ord','Rcvd Date','Qty Rec','Receiving Clerk Notes','Material Manager Notes'],
        colModel: [
            {   name:'id',
                index:'id',
                hidden:true,
                key:false,
                search:false,
                viewable:false
            },
            {   name:'type',
                index:'type',
                width:35,
                sortable:false,
                editable:false,
                align:'center',
                editoptions:{defaultValue:'M'}
            },
            {   name:'supp',
                index:'supp',
                width:35,
                sortable:false,
                editable:false,
                align:'center',
                editoptions:{defaultValue:suppno}
            },
            {   name:'vendor_id',
                index:'o.vendor_id',
                width:0,
                hidden:true,
                search:false,
                align:'center',
                viewable:true,
                editable:true,
                edittype:'text',
                editoptions:{size:8,readonly:true}
            },
            {   name:'vendor',
                index:'o.vendor_id',
                width:90,
                sortable:true,
                sorttype:'text',
                align:'left',
                editable:true,
                classes:'ui-ellipsis',
                edittype:'text',
                editoptions:{size:20,readonly:true},
                editrules:{required:true}
            },
            {   name:'order_number',
                index:'order_number',
                width:55,
                sortable:true,
                editable:true,
                classes:'ui-ellipsis',
                align:'center'
            },
            {   name:'mastec_partno',
                index:'mastec_partno',
                width:120,
                sortable:false,
                editable:true,
                classes:'ui-ellipsis',
                edittype:'text',
                editoptions:{
                    size:22,
                    dataInit:function(e) {
                        $(e).autocomplete(mmAutoCompOpts);
                    }
                },
                editrules:{required:true}
            },
            {   name:'mfgr_partno',
                index:'mfgr_partno',
                width:120,
                sortable:false,
                editable:true,
                classes:'ui-ellipsis',
                alilgn:'left',
                edittype:'text',
                editoptions:{size:22,readonly:true},
                editrules:{required:false}
            },
            {   name:'description',
                index:'description',
                width:180,
                sortable:false,
                align:'left',
                editable:true,
                classes:'ui-ellipsis',
                edittype:'text',
                editoptions:{size:33,readonly:true},
                editrules:{required:true}
            },
            {   name:'ship_date',
                index:'o.ship_date',
                width:85,
                sortable:true,
                sorttype:'date',
                editable:true,
                align:'center',
                editrules:{required:true},
                editoptions:{   size:15,
                                dataInit: function(l) {
                                    $(l).datepicker({dateFormat:'yy-mm-dd'});
                                }
                            }
            },
            {   name:'qty_ordered',
                index:'qty_ordered',
                width:55,
                sortable:false,
                editable:true,
                align:'center',
                classes:'qtyOrd',
                editrules:{required:true},
                editoptions:{size:6}
            },
            {   name:'rcvd_date',
                index:'o.rcvd_date',
                width:85,
                sortable:true,
                sorttype:'date',
                editable:true,
                align:'center',
                editoptions:{   size:15,
                                dataInit:function(l) {
                                    $(l).datepicker({dateFormat:'yy-mm-dd'});
                                }
                            }
            },
            {   name:'qty_received',
                index:'qty_received',
                width:55,
                sortable:true,
                editable:true,
                align:'center',
                classes:'qtyRec',
                editoptions:{size:6}
            },
            {   name:'rc_notes',
                index:'rc_notes',
                width:250,
                sortable:false,
                editable:true,
                edittype:'textarea',
                classes:'ui-ellipsis',
                editoptions:{rows:'3',cols:'45'}
            },
            {   name:'mm_notes',
                index:'mm_notes',
                width:250,
                sortable:false,
                editable:true,
                edittype:'textarea',
                classes:'ui-ellipsis',
                editoptions:{rows:'3',cols:'45'}
            }
        ],
        pager:'#orderMMFoot',
        sortname:'o.id',
        caption:'Minor Materials Ordered for ' + ml_name,
        afterInsertRow: function(id) {
            $('tr#' + id).each(function() {
                var qtyord = $(this).find('td.qtyOrd').text();
                var qtyrec = $(this).find('td.qtyRec').text();
                if ((+qtyord === +qtyrec) && (qtyrec !== null) && (qtyrec !== 'undefined') && (qtyrec !== '')) {
                    $(this).find('td.qtyRec').removeClass('incomplete').addClass('complete');
                } else {
                    $(this).find('td.qtyRec').removeClass('complete').addClass('incomplete');
                }
            });
        },
        gridComplete: function() {
            $('.jqgrow').each(function() {
                var qtyord = $(this).find('td.qtyOrd').text();
                var qtyrec = $(this).find('td.qtyRec').text();
                if ((+qtyord === +qtyrec) && (qtyrec !== null) && (qtyrec !== 'undefined') && (qtyrec !== '')) {
                    $(this).find('td.qtyRec').removeClass('incomplete').addClass('complete');
                } else {
                    $(this).find('td.qtyRec').removeClass('complete').addClass('incomplete');
                }
            });
        },
        onSelectRow: function(id) {
            if(id && id !== lastSel) {
                mmGrid.jqGrid('restoreRow',lastSel);
                lastSel = id;
            }
            mmGrid.jqGrid('editRow',id,true);
            $('#orderMMGrid_ilsave').removeClass('ui-state-disabled');
            $('#orderMMGrid_ilcancel').removeClass('ui-state-disabled');
        },
        editurl:'/jqg/jqg.saveMinorMaterialEdit.php'
    });
    mmGrid.jqGrid('navGrid','#orderMMFoot',{
        add:false,
        edit:false,
        del:true
    });
    mmGrid.jqGrid('inlineNav','#orderMMFoot',{
        add:true,
        edit:true,
        editParams:mmEditParam,
        addParams:mmAddParam
    });
});

And here is the first jqGrid definition (AFTER), using comments and answer..

function hiliteQty(i) {
    console.log('Highlighting received quantity on #' + i);
    $eRow = $('tr#' + i);
    var qtyord = $eRow.find('td.qtyOrd').text();
    var qtyrec = $eRow.find('td.qtyRec').text();
    if ((+qtyord === +qtyrec) && (qtyrec !== null) && (qtyrec !== 'undefined') && (qtyrec !== '')) {
        $eRow.find('td.qtyRec').removeClass('incomplete',100,'linear').addClass('complete',1000,'easeInElastic');
    } else {
        $eRow.find('td.qtyRec').removeClass('complete',100,'linear').addClass('incomplete',1000,'easeInElastic');
    };
}
function rcvAll(r) {
    var d = dateFormat('isoDate');
    var gridid;
    $.each(r, function(i,v) {
        var $r = $('#' + v);
        gridid = $r.closest('table').attr('id');
        var qtyOrd = $r.find('.qtyOrd').text();
        $('#' + gridid).jqGrid('editRow', v);
        if ( $r.find('.qtyRec > input').val() !== qtyOrd.parseInt() ) {
            $r.find('.qtyRec > input').val(qtyOrd);
            $r.find('.rcvDate > input').val(d);
            console.log(dateFormat('isoMicro'));
            $('#' + gridid).jqGrid('saveRow', v, false);
            console.log(dateFormat('isoMicro'));
        }
    });
    $('#' + gridid).trigger('reloadGrid');
}
$(function() {
    var ml_id = '<?=$ml_id;?>', ml_name = '<?=$objML_temp->showMLName();?>', suppno = '<?=$objML_temp->gSupp();?>', projnum = '<?=$objJob_temp->gProjectNumber();?>', job_id = '<?=$objML_temp->gJobID();?>', lastDate;
    $('#special_dialog').dialog({
        width:'auto',
        height:'auto',
        resizable:true
    });
    $.extend($.jgrid.defaults,{
        inlineData:{
            ml_id:ml_id,
            project_number:projnum,
            job_id:job_id
        },
        rowNum:1000,
        rowList:[20,50,100,500,1000],
        viewrecords:true,
        sortorder:'asc',
        height:500,
        autowidth:true,
        deepempty:true,
        altRows: true,
        grouping: true,
        groupingView: {
            groupField: ["vendor"],
            groupColumnShow: [true],
            groupText: ["<b>VENDOR: {0}</b>"],
            groupDataSorted: true,
            groupSummary: [false]
        }
    });
    //////////////////////////////
    // setup Minor Materials grid
    //////////////////////////////
    var $mmGrid = $('#orderMMGrid'),
        $mmFoot = $('#orderMMFoot'),
        mmEditParam = {
            keys: true,
            oneditfunc: function(id) {
                $('#orderMMGrid_ilsave').removeClass('ui-state-disabled');
                $('#orderMMGrid_ilcancel').removeClass('ui-state-disabled');
                hiliteQty(id);
            },
            aftersavefunc: function(id) {
                hiliteQty(id);
            }
        },
        mmAddParam = {
            rowID: 'new',
            position:'last',
            addRowParams: mmEditParam
        },
        mmAutoCompOpts = {
            source: function(request, response) {
                $.getJSON('/json/json.searchmultiMaterials.php',{term:request.term,type:'m'},function(data) {
                    response(data);
                });
            },
            minLength: 3,
            focus: function(e,ui) {
                $('input:text[name="description"]').val(ui.item.description);
                $('input:text[name="vendor"]').val(ui.item.vendor);
                $('input:text[name="mfgr_partno"]').val(ui.item.mfgr_partno);
            },
            select: function(e,ui) {
                $('input:text[name="description"]').val(ui.item.description);
                $('input:text[name="vendor"]').val(ui.item.vendor);
                $('input:text[name="mfgr_partno"]').val(ui.item.mfgr_partno);
                $('input:text[name="vendor_id"]').val(ui.item.vendor_id);
            }
        };
    $mmGrid.jqGrid({
        url: '/json/json.getMinorMaterialsOrder.php?ml_id=' + ml_id,
        datatype:'json',
        emptyrecords: 'No Minor Materials on this order',
        colNames: ['ID','Type','Supp','VID','Vendor','PO#','MasTec Part#','Manufacturer Part#','Description','Ship Date','Qty Ord','Rcvd Date','Qty Rec','Receiving Clerk Notes','Material Manager Notes'],
        colModel: [
            {   name:'id',
                index:'id',
                hidden:true,
                key:false,
                search:false,
                viewable:false
            },
            {   name:'type',
                index:'type',
                width:35,
                sortable:false,
                editable:false,
                align:'center',
                editoptions:{defaultValue:'M'}
            },
            {   name:'supp',
                index:'supp',
                width:35,
                sortable:false,
                editable:false,
                align:'center',
                editoptions:{defaultValue:suppno}
            },
            {   name:'vendor_id',
                index:'o.vendor_id',
                width:0,
                hidden:true,
                search:false,
                align:'center',
                viewable:true,
                editable:true,
                edittype:'text',
                editoptions:{size:8,readonly:true}
            },
            {   name:'vendor',
                index:'o.vendor_id',
                width:90,
                sortable:true,
                sorttype:'text',
                align:'left',
                editable:true,
                classes:'ui-ellipsis',
                edittype:'text',
                editoptions:{size:20,readonly:true},
                editrules:{required:true}
            },
            {   name:'order_number',
                index:'order_number',
                width:55,
                sortable:true,
                editable:true,
                classes:'ui-ellipsis',
                align:'center'
            },
            {   name:'mastec_partno',
                index:'mastec_partno',
                width:120,
                sortable:false,
                editable:true,
                classes:'ui-ellipsis',
                edittype:'text',
                editoptions:{
                    size:22,
                    dataInit:function(e) {
                        $(e).autocomplete(mmAutoCompOpts);
                    }
                },
                editrules:{required:true}
            },
            {   name:'mfgr_partno',
                index:'mfgr_partno',
                width:120,
                sortable:false,
                editable:true,
                classes:'ui-ellipsis',
                alilgn:'left',
                edittype:'text',
                editoptions:{size:22,readonly:true},
                editrules:{required:false}
            },
            {   name:'description',
                index:'description',
                width:180,
                sortable:false,
                align:'left',
                editable:true,
                classes:'ui-ellipsis',
                edittype:'text',
                editoptions:{size:33,readonly:true},
                editrules:{required:true}
            },
            {   name:'ship_date',
                index:'o.ship_date',
                width:85,
                sortable:true,
                sorttype:'date',
                editable:true,
                align:'center',
                editrules:{required:true},
                editoptions:{   size:15,
                                dataInit: function(l) {
                                    $(l).datepicker({dateFormat:'yy-mm-dd'});
                                }
                            }
            },
            {   name:'qty_ordered',
                index:'qty_ordered',
                width:55,
                sortable:false,
                editable:true,
                align:'center',
                classes:'qtyOrd',
                editrules:{required:true},
                editoptions:{size:6}
            },
            {   name:'rcvd_date',
                index:'o.rcvd_date',
                width:85,
                sortable:true,
                classes:'rcvDate',
                sorttype:'date',
                editable:true,
                align:'center',
                editoptions:{   size:15,
                                dataInit:function(l) {
                                    $(l).datepicker({dateFormat:'yy-mm-dd'});
                                }
                            }
            },
            {   name:'qty_received',
                index:'qty_received',
                width:55,
                sortable:true,
                editable:true,
                align:'center',
                classes:'qtyRec',
                cellattr:function(rowId,val,rawObj,cm,rdata) {
                    if (val === rawObj.qty_ordered) {
                        return ' class="complete"';
                    } else {
                        return ' class="incomplete"';
                    }
                },
                editoptions:{size:6}
            },
            {   name:'rc_notes',
                index:'rc_notes',
                width:250,
                sortable:false,
                editable:true,
                edittype:'textarea',
                classes:'ui-ellipsis',
                editoptions:{rows:'3',cols:'45'}
            },
            {   name:'mm_notes',
                index:'mm_notes',
                width:250,
                sortable:false,
                editable:true,
                edittype:'textarea',
                classes:'ui-ellipsis',
                editoptions:{rows:'3',cols:'45'}
            }
        ],
        pager:'#orderMMFoot',
        sortname:'o.id',
        caption:'Minor Materials Ordered for ' + ml_name,
        onSelectRow: function(id) {
            var savedRows = $mmGrid.jqGrid('getGridParam','savedRow');
            if(savedRows.length > 0) {
                $mmGrid.jqGrid('restoreRow', savedRows[0].id);
            }
            $mmGrid.jqGrid('editRow', id, mmEditParam);
        },
        editurl:'/jqg/jqg.saveMinorMaterialEdit.php'
    });
    $mmGrid
    .jqGrid('navGrid','#orderMMFoot',{
        add:false,
        edit:false,
        del:true
    })
    .jqGrid('navSeparatorAdd','#orderMMFoot',{
        sepclass:'ui-separator',
        sepcontent:''
    })
    .jqGrid('navButtonAdd','#orderMMFoot',{
        title:'Receive All',
        caption:'',
        buttonicon:'ui-icon-cart',
        onClickButton:function() {
            var dataRowIDs = $mmGrid.jqGrid('getDataIDs');
            rcvAll(dataRowIDs);
        },
        position:'last'
    })
    .jqGrid('navSeparatorAdd','#orderMMFoot',{
        sepclass:'ui-separator',
        sepcontent:''
    })
    .jqGrid('inlineNav','#orderMMFoot',{
        add:true,
        edit:true,
        save:true,
        cancel:true,
        editParams:mmEditParam
    });
Community
  • 1
  • 1
DevlshOne
  • 8,357
  • 1
  • 29
  • 37
  • 1
    It's very strange that you use `mmAddParam` and other defined as `{ rowID: 'new', position:'last' }`. I would expect that you use at least `mmAddParam: { rowID: 'new', position:'last', addRowParams: mmEditParam }`. It would mean the usage of `mmEditParam` (inclusive `aftersavefunc`) during Add of new row too. – Oleg Aug 18 '14 at 16:22
  • @Oleg I'm sorry, I'm not quite sure I understand what you're saying. Do I need to move some of my code around to get things to work right? – DevlshOne Aug 18 '14 at 19:21
  • 1
    I see many small problems in your code. Moreover one can reduce the code in many times to share the same code fragments for different grids. Nevertheless the main problem which I see is: you specify `keys: true`, `aftersavefunc` and other editing options **only for Edit button**. Add button don't use the options. If you use some old version of jqGrid you can have event more problems. You have to use `keys: true`, `aftersavefunc` and other editing options you have to specify it as `addRowParams` of addParam options. Just try to add `addRowParams: mmEditParam` property to `mmAddParam` & use Add. – Oleg Aug 18 '14 at 20:49
  • 1
    One clear error is inside of `onSelectRow`. For example `mmGrid.jqGrid('editRow',id,true)` need be replaced to `mmGrid.jqGrid('editRow',id,mmEditParam)`. Another problem: `editingRowId` variable will be **shared** for multiple grids. So the value for one grid will be overwritten by another one. It *only one row* can be editing in one grid at the same time then you can use `savedRow` parameter instead of `editingRowId` variable (see [the answer](http://stackoverflow.com/a/24933514/315935) for example) – Oleg Aug 18 '14 at 20:56
  • @Oleg, very helpful, thanks! I'd had no experience with jqGrid before starting that script. I was using several mixed examples, the documentation and as much info as I could from SO. I see what you mean about the redundant parameters and how I seem to have missed the mark on re-using a lot of the code over multiple grids. Again, many thanks. – DevlshOne Aug 18 '14 at 21:10
  • You are welcome! I recommend you use `this` inside of jqGrid callbacks. For example `mmGrid` inside of `onSelectRow` callback can be replaced to `$(this)`. In the same way strings like `'#orderOMGrid_ilsave'` contains `orderOMGrid` prefix which can you get as `this.id`. – Oleg Aug 18 '14 at 21:45
  • Moreover I strictly recommend you don't use `afterInsertRow` and modification of every row of grid inside of `gridComplete`. Instead of that one should use `gridview: true` (see [the answer](http://stackoverflow.com/a/12519858/315935)) and `cellattr` or `rowattr`. It can dramatically improve performance of the page especially if grid have many rows. Look at [the answer](http://stackoverflow.com/a/6048865/315935) (look at `rawObject` parameter like in [the answer](http://stackoverflow.com/a/7408355/315935)) and [this one](http://stackoverflow.com/a/10531680/315935). – Oleg Aug 18 '14 at 21:50

1 Answers1

0

The main problem in the code: one should use XXEditParam (like mmEditParam) inside of onSelectRow. For example one should replace mmGrid.jqGrid('editRow',id,true) to mmGrid.jqGrid('editRow',id,mmEditParam).

Another important problem: the current code specify keys: true, aftersavefunc and other editing options only for Edit button. Add button don't use the options. If you use some old version of jqGrid you can have event more problems. You have to use keys: true, aftersavefunc and other editing options you have to specify it as addRowParams of addParam options. Just try to add addRowParams: mmEditParam property to mmAddParam and use Add. You will see that keys: true, aftersavefunc and other editing option will start work in case of usage Add button.

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • I've posted up a post-answer, modified version of my grid definition which I believe has some improvements but I'm still having issues. The ENTER key still does not fire off the 'aftersavefunc' event, which I need to relay the visual cue to my users that the QTY RECEIVED amount they have entered does or does not match the QTY ORDERED amount. It works fine at the 'cellattr' method. Also, should I really need to remove the 'disabled' class of the save and cancel icons when editing begins? Thanks. – DevlshOne Aug 19 '14 at 00:39