Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jqGrid access cell data while it is being edited

I'm currently using afterSaveCell to handle manually updating some cells in a grid. I have this working fine if the user uses enter to save the currently editing cell.

Unfortunately, if they click or tab out of the cell they are editing directly into another cell I can no longer grab the cell value of the newly edited cell as getCell will only return the html for the input control.

In summary, is there any way to access the value of the cell even while it is being edited?

jQuery(document).ready(function () {
    var mydata = [
        {id:"1", invdate:"2007-10-01",name:"test",  note:"note",  amount:"200.00",tax:"10.00",total:"210.00"},
        {id:"2", invdate:"2007-10-02",name:"test2", note:"note2", amount:"300.00",tax:"20.00",total:"320.00"},
        {id:"3", invdate:"2007-09-01",name:"test3", note:"note3", amount:"400.00",tax:"30.00",total:"430.00"},
        {id:"4", invdate:"2007-10-04",name:"test",  note:"note4", amount:"200.00",tax:"10.00",total:"210.00"},
        {id:"5", invdate:"2007-10-05",name:"test5", note:"note5", amount:"300.00",tax:"20.00",total:"320.00"},
        {id:"6", invdate:"2007-09-06",name:"test",  note:"note6", amount:"400.00",tax:"30.00",total:"430.00"},
        {id:"7", invdate:"2007-10-04",name:"test7", note:"note7", amount:"200.00",tax:"10.00",total:"210.00"},
        {id:"8", invdate:"2007-10-03",name:"test8", note:"note8", amount:"300.00",tax:"20.00",total:"320.00"},
        {id:"9", invdate:"2007-09-01",name:"test",  note:"note9", amount:"400.00",tax:"30.00",total:"430.00"},
        {id:"10",invdate:"2007-09-08",name:"test10",note:"note10",amount:"500.00",tax:"30.00",total:"530.00"},
        {id:"11",invdate:"2007-09-08",name:"test11",note:"note11",amount:"500.00",tax:"30.00",total:"530.00"},
        {id:"12",invdate:"",name:"TOTAL",  note:"",amount:"",tax:"",total:""}
    ];

    var grid = $("#list");

    grid.jqGrid({
        cellsubmit: 'remote',
        cellurl: '/Example/GridSave',
        datatype: "local",
        data: mydata,
        mtype: 'POST',
        colNames: ['Inv No', 'Date', 'Client', 'Amount', 'Tax', 'Total', 'Notes'],
        colModel: [
            { name: 'id', index: 'id', width: 65, sorttype: 'int', hidden: true },
            { name: 'invdate', index: 'invdate', width: 120, align: 'center', formatter: 'date', formatoptions: { newformat: 'd-M-Y' }, sortable: false },
            { name: 'name', index: 'name', editable: true, width: 90, sortable: false },
            { name: 'amount', index: 'amount', editable: true, width: 70, formatter: 'number', align: 'right', sortable: false },
            { name: 'tax', index: 'tax', editable: true, width: 60, formatter: 'number', align: 'right', sortable: false },
            { name: 'total', index: 'total', editable: true, width: 60, formatter: 'number', align: 'right', sortable: false },
            { name: 'note', index: 'note', width: 100, sortable: false }
        ],
        rowNum: 1000,
        pager: '#pager',
        viewrecords: true,
        sortorder: "desc",
        caption: "afterSaveCell Issue",
        height: "100%",
        cellEdit: true,
        gridComplete: function () {
            calculateTotal();
        },
        afterSaveCell: function (rowid, name, val, iRow, iCol) {
            calculateTotal();
        }
    });
});

function calculateTotal() {
    var totalAmount = 0;
    var totalTax = 0;

    var grid = jQuery("#list");

    var ids = grid.jqGrid('getDataIDs');
    for (var i = 0; i < ids.length; i++) {
        var id = ids[i];

        if (grid.jqGrid('getCell', id, 'name') === "TOTAL") {
            grid.jqGrid('setRowData', id, {
                'amount': totalAmount,
                'tax': totalTax,
                'total': totalAmount + totalTax
            });
        }
        else {
            totalAmount += Number(grid.jqGrid('getCell', id, 'amount'));
            totalTax += Number(grid.jqGrid('getCell', id, 'tax'));
        }
    }
}

Thanks in advance!

like image 616
Shawn Avatar asked Feb 25 '11 18:02

Shawn


3 Answers

I see two problems in your code. The first one is more cosmetic, but the correct solution can simplify many things in the future.

The first problem is that you add manual the "TOTAL" row as a part of grid data and calculate the values in the row inside calculateTotal function. The better way is to use footerrow:true option, which add additional row at the bottom of grid which will be not mixed with the grid data. For server based data you can use userdata part of JSON or XML response from the server and use userDataOnFooter:true additionally to till the data from the userData jqGrid parameter to the footer row. In case of "local" datatype one can use footerData method to set (or get) the data in the footer. Additionally the method getCol can be used co calculate the sum of elements in the column. So your version of calculateTotal function can be rewritten as

var grid = $("#list");
var calculateTotal = function() {
    var totalAmount = grid.jqGrid('getCol','amount',false,'sum'),
        totalTax = grid.jqGrid('getCol','tax',false,'sum');
    grid.jqGrid('footerData','set',{name:'TOTAL',amount:totalAmount,tax:totalTax});
}

Now to your main problem. You use cell edit mode. If the function calculateTotal (your original or my simplified version) will be called at the time when one from the cells of the 'amount' or 'tax' are in the editing mode, the calculateTotal will be read HTML fragment with <input> element instead of the string with the number and the calculation will failed.

I created the small demo which call calculateTotal every second. So if you click on any cell from the 'amount' or 'tax' column you will see that in the footer row 0 will be displayed as the sum. So the demo having cellsubmit:'clientArray' has the same problem as in your original code with cellsubmit:'remote'.

To solve the problem one can use data parameter of jqGrid during the sum calculation:

var grid = $("#list");
var calculateTotal = function() {
    var gridData = grid.jqGrid('getGridParam','data'),
        i=0,totalAmount=0,totalTax=0;
    for (;i<gridData.length;i++) {
        var rowData = gridData[i];
        totalAmount += Number(rowData.amount);
        totalTax += Number(rowData.tax);
    }
    grid.jqGrid('footerData','set',{name:'TOTAL',amount:totalAmount,tax:totalTax});
}

The corresponding fixed demo you will find here. In your final code you can remove

setInterval(calculateTotal, 1000);

which I used for demonstration purpose only and refresh the footer in the afterSaveCell event handler only.

UPDATED: If you work with remote data you can not use data parameter. So one have to get data from the <input> element if needed. I created one more demo which demonstrate how one can do this. The code of calculateTotal will be longer:

var getColumnIndexByName = function(grid,columnName) {
    var cm = grid.jqGrid('getGridParam','colModel');
    for (var i=0,l=cm.length; i<l; i++) {
        if (cm[i].name===columnName) {
            return i; // return the index
        }
    }
    return -1;
},
getTextFromCell = function(cellNode) {
    return cellNode.childNodes[0].nodeName === "INPUT"?
           cellNode.childNodes[0].value:
           cellNode.textContent || cellNode.innerText;
},
calculateTotal = function() {
    var totalAmount = 0, totalTax = 0,
        i=getColumnIndexByName(grid,'amount');
    $("tbody > tr.jqgrow > td:nth-child("+(i+1)+")",grid[0]).each(function() {
        totalAmount += Number(getTextFromCell(this));
    });

    i=getColumnIndexByName(grid,'tax');
    $("tbody > tr.jqgrow > td:nth-child("+(i+1)+")",grid[0]).each(function() {
        totalTax += Number(getTextFromCell(this));
    });

    grid.jqGrid('footerData','set',{name:'TOTAL',amount:totalAmount,tax:totalTax});
};
like image 162
Oleg Avatar answered Nov 13 '22 11:11

Oleg


Thanks oleg the solution for me was applying and changing what you put

var ListTabla="ListFormatos";
var request="../../tabla_general/tabla_general_mantenimiento.php";

var getColumnIndexByName = function(grid,columnName) {
var cm = $("#"+grid).jqGrid('getGridParam','colModel');
for (var i=0,l=cm.length; i<l; i++) {
    if (cm[i].name===columnName) {
        return i; // return the index
    }
}
return -1;
},

getTextFromCell = function(cellNode) {
return cellNode.childNodes[0].nodeName === "INPUT"?
       cellNode.childNodes[0].value:
       cellNode.textContent || cellNode.innerText;
},

calculateTotal = function(grid) {   

total_hpr_suebas = retorna_suma('hpr_suebas',grid);
total_hpr_asifam = retorna_suma('hpr_asifam',grid);
total_hpr_bashpr = retorna_suma('hpr_bashpr',grid);
total_hpr_remcom = retorna_suma('hpr_remcom',grid);
total_hpr_basmes = retorna_suma('hpr_basmes',grid);
total_hpr_provcts = retorna_suma('hpr_provcts',grid);
total_hpr_provgrat = retorna_suma('hpr_provgrat',grid);
total_hpr_provvac=retorna_suma('hpr_provvac',grid);

    $("#"+grid).jqGrid('footerData','set',{sec_detsec:'TOTAL',hpr_suebas:total_hpr_suebas,hpr_asifam:total_hpr_asifam,hpr_bashpr:total_hpr_bashpr,hpr_remcom:total_hpr_remcom,hpr_basmes:total_hpr_basmes,hpr_provcts:total_hpr_provcts,hpr_provgrat:total_hpr_provgrat,hpr_provvac:total_hpr_provvac});
};

retorna_suma=function(campo,grid)
{
    total=0;
    i=getColumnIndexByName(grid,campo);
    $("tbody > tr.jqgrow > td:nth-child("+(i+1)+")",$("#"+grid)[0]).each(function() {
        total+= Number(getTextFromCell(this));
    });
    return total;
}

function fn_jqgrid_history_provisiones_trabajador(tra_idtra,fecha_inicio,fecha_fin)
{
    jQuery("#"+ListTabla).jqGrid({
                    url:request+"?action=search_history_provisiones_trabajador&tra_idtra="+tra_idtra+"&fecha_inicio="+fecha_inicio+"&fecha_fin="+fecha_fin,
                    async: false,
                    datatype: 'json',
                    colNames:['','ID','SECTOR','BASICO','ASIG. FAM','DIAS','BASE','REM. COMP.','BASE MES','P.CTS','P.GRAT.','P.VAC.','MES','ANIO','PORC.','SAL.VAC.','SAL.GRAT.'],
                    colModel:[
                         {name:'act', index:'act', width:50, resizable:true, align:"center",hidden:true},
                        {name:'id', index:'id', width:50, resizable:true, align:"center",hidden:true},
                        {name:'sec_detsec', index:'sec_detsec', width:80},
                        {name:'hpr_suebas', index:'hpr_suebas', width:60},
                        {name:'hpr_asifam', index:'hpr_asifam', width:50},
                        {name:'hpr_numdia', index:'hpr_numdia', width:30},
                        {name:'hpr_bashpr',index:'hpr_bashpr', width:60},
                        {name:'hpr_remcom,',index:'hpr_remcom', width:60},
                        {name:'hpr_basmes', index:'hpr_basmes', width:60},
                        {name:'hpr_provcts', index:'hpr_provcts', width:60},
                        {name:'hpr_provgrat', index:'hpr_provgrat', width:60},
                        {name:'hpr_provvac', index:'hpr_provvac', width:60},
                        {name:'hpr_meshpr', index:'hpr_meshpr', width:30},
                        {name:'hpr_aniohpr,',index:'hpr_aniohpr', width:30},
                        {name:'hpr_salpor', index:'hpr_salpor', width:50},
                        {name:'hpr_salval_vac', index:'hpr_salval_vac', width:50},
                        {name:'hpr_salval_grat', index:'hpr_salval_grat', width:50}
                    ],
                    pager: '#paginacion',
                    rowNum:10,
                    rowList:[10,20,30],
                    sortname: 'ID',
                    ondblClickRow:function(rowid, iRow, iCol, e)
                    {
                                obj=jQuery("#"+ListTabla).jqGrid('getRowData',rowid);
                    }
                    ,
                    sortorder: 'desc',
                    editurl:request,
                    viewrecords: true,
                    caption: 'Provisiones',
                    //rownumbers: true,
                     height: 250,
                    rowheight: 280,
                    footerrow : true,
                    gridComplete: function () {
                        calculateTotal(ListTabla);
                },
                    afterSaveCell: function (rowid, name, val, iRow, iCol) {
                        //calculateTotal(ListTabla);
                    }
                    }).navGrid('#paginacion',{add:false,edit:false, del:false});

                        jQuery("#"+ListTabla).jqGrid('bindKeys', {"onEnter":function( rowid ) {
                                                                    obj=jQuery("#"+ListTabla).jqGrid('getRowData',rowid);
                                                                    } } );  

                 }
like image 1
user1413147 Avatar answered Nov 13 '22 13:11

user1413147


If you just want to recalculate total number, you can use trigger to reload the grid in afterSaveCell event. Like this:

afterSaveCell: function (rowid, name, val, iRow, iCol) 

        {
          jQuery("#list11").jqGrid('setGridParam',{datatype:'local',loadonce:true}).trigger('reloadGrid');
        }
like image 1
Julia Avatar answered Nov 13 '22 13:11

Julia