2011-02-25 16 views
6

Actualmente estoy usando afterSaveCell para manejar manualmente la actualización de algunas celdas en una grilla. Esto funciona bien si el usuario usa enter para guardar la celda de edición actual.jqGrid acceder datos de la celda mientras se está editando

Desafortunadamente, si hacen clic o salen de la celda que están editando directamente en otra celda, ya no puedo tomar el valor de la celda recién editada ya que getCell solo devolverá el html para el control de entrada.

En resumen, ¿hay alguna forma de acceder al valor de la celda incluso mientras se está editando?

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')); 
     } 
    } 
} 

¡Gracias de antemano!

+0

Si necesita guardar celda actual en la ficha que habrá sobrescribir la aplicación por defecto de '' nextCell' y prevCell' que será llamado el TAB o Shift-TAB. Vea el código de las funciones aquí: https://github.com/tonytomov/jqGrid/blob/master/js/grid.celledit.js#L305 – Oleg

+0

Gracias @Oleg, eso definitivamente ayudaría al problema de TAB, pero aún deja el problema cuando se difumina en otra celda en la misma cuadrícula. – Shawn

+0

Tiene razón acerca de la borrosidad. Probablemente, la forma de vincular el elemento de edición al evento 'blur' o incluso 'focusout' podría resolver su problema. Puede usar 'dataEvents' (vea http://stackoverflow.com/questions/4407273/jqgrid-retrieve-data-of-cell-and-manipulate-it/4407958#4407958) en' editoptions' para enlazar a la evento 'focusout' y llame a "saveCell". También puede usar 'beforeEditCell' para guardar el último' iRow', 'iCol' necesario como parámetros en' saveCell'. – Oleg

Respuesta

11

Veo dos problemas en su código. El primero es más cosmético, pero la solución correcta puede simplificar muchas cosas en el futuro.

El primer problema es que agrega manualmente la fila "TOTAL" como parte de los datos de la cuadrícula y calcula los valores en la fila dentro de la función calculateTotal. La mejor manera es usar la opción footerrow:true, que agrega una fila adicional en la parte inferior de la cuadrícula que será no mezclada con los datos de la cuadrícula. Para datos basados ​​en servidor, puede usar userdata parte de la respuesta JSON o XML del servidor y usar userDataOnFooter:true adicionalmente para ajustar los datos del parámetro userData jqGrid a la fila del pie de página. En el caso del tipo de datos "local", se puede usar el método footerData para establecer (u obtener) los datos en el pie de página. Además, el método getCol se puede usar para calcular la suma de elementos en la columna. Por lo que su versión de calculateTotal función puede ser reescrito como

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}); 
} 

ahora a su problema principal. Usas el modo de edición de celda. Si se llamará a la función calculateTotal (su versión original o mi versión simplificada) en el momento en que una de las celdas de 'monto' o 'impuesto' está en el modo de edición, el calculateTotal se leerá fragmento HTML con el elemento <input> en lugar de la cadena con el número y el cálculo fallará.

Creé the small demo que llaman calculateTotal cada segundo. Por lo tanto, si hace clic en cualquier celda de 'cantidad' o columna 'impuesto', verá que en la fila de pie de página 0 se mostrará como suma. Entonces la demo que tiene cellsubmit:'clientArray' tiene el mismo problema que en su código original con cellsubmit:'remote'.

Para resolver el problema se puede utilizar data parámetro de jqGrid durante el cálculo de la suma:

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}); 
} 

La demostración correspondiente fijo se encuentra here. En su código final puede quitar

setInterval(calculateTotal, 1000); 

que he utilizado con fines de demostración solamente y refrescar el pie de página sólo en el controlador de afterSaveCell evento.

ACTUALIZADO: Si trabaja con datos remotos no puede usar el parámetro data. Entonces uno tiene que obtener datos del elemento <input> si es necesario. Creé one more demo que demuestran cómo se puede hacer esto.El código de calculateTotal será más largo:

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}); 
}; 
+0

Parece que 'jqGrid ('getGridParam', 'data')' solo funciona con datos locales. Usarlo con mis datos remotos json es devolver una cadena vacía. – Shawn

+0

@Shawn: Sí, es correcto, pero su demostración ha utilizado datos locales. Si necesita utilizar datos remotos, debe examinar si los datos de 'getCell' son fragmentos HTML con' ' o no. En lugar de la enumeración de identificadores de fila, puede usar una forma más rápida de jQuery, que describí en http://stackoverflow.com/questions/5010761/linking-from-a-column-value-in-jqgrid-to-a-new-page. -using-get/5017528 # 5017528. Para hacerlo más fácil, creé una demo más http://www.ok-soft-gmbh.com/jqGrid/CellEditAfterSaveCellProblem1.htm que hace lo que necesita. – Oleg

+0

@Oleg: ¡excelente respuesta! Tengo una pregunta más - Tengo inisde my row a select type cell - ¿cómo puedo resumir la cantidad total solo cuando el valor de selección es el primer valor dentro de ella? Quiero decir que quiero calcular la suma dependiendo del valor dentro de la celda de selección. gracias ... – user590586

1

Gracias Oleg la solución para mí estaba aplicando y cambiando lo que se pone

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); 
                    } }); 

       } 
1

Si lo que desea es volver a calcular total, puede utilizar el gatillo para recargar la grilla en el evento afterSaveCell. De esta manera:

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

     { 
      jQuery("#list11").jqGrid('setGridParam',{datatype:'local',loadonce:true}).trigger('reloadGrid'); 
     } 
Cuestiones relacionadas