Bezdepbonusu7Программирование: статьи и ответы

Вопрос

JqGrid получает доступ к данным ячейки во время их редактирования

Автор вопроса: ShawnОтветов: 3

В настоящее время я использую afterSaveCell для ручного обновления некоторых ячеек в сетке. У меня это работает нормально, если пользователь использует ввод, чтобы сохранить текущую редактируемую ячейку.

К сожалению, если они щелкнут или выйдут из ячейки, которую они редактируют, непосредственно в другую ячейку, я больше не смогу получить значение ячейки только что отредактированной ячейки, поскольку getCell вернет только html для элемента управления вводом.

Таким образом, есть ли способ получить доступ к значению ячейки даже во время ее редактирования?

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

Заранее спасибо!

  • Если вам нужно сохранить текущую ячейку на TAB, вы будете перезаписывать реализацию по умолчанию nextCell и prevCell, которые будут вызываться на TAB или Shift-TAB. См. код функций здесь: github.com/ tonytomov/jqGrid/blob/master/js/ Oleg 25.02.2011
  • Спасибо @Oleg, это определенно помогло бы решить проблему TAB, но по-прежнему оставляет проблему при размытии на другую ячейку в той же сетке. Shawn 26.02.2011
  • Вы правы насчет размытия. Вероятно, способ привязки элемента редактирования к событию "размытие" или даже "фокусировка" может решить вашу проблему. Вы можете использовать dataEvents (см. ячейку и манипулировать ею">stackoverflow.com/questions/4407273/) в editoptions, чтобы сделать привязку к событию focusout и вызвать saveCell. Вы можете дополнительно использовать beforeEditCell для сохранения последних iRow, iCol необходимых параметров в файле saveCell. Oleg 26.02.2011
  • Я перечитал ваш вопрос еще раз и не уверен, что правильно понял вас раньше. Мне кажется, что вы хотите просто иметь доступ к ячейке, содержащейся внутри специального события. Не имея кода, который более четко описывает вашу проблему, я, вероятно, не смогу вам помочь. Oleg 26.02.2011
  • Я попытался создать пример, используя clientArray, но он не воспроизводит ошибку. Кажется, что задержка при отправке новых данных ячейки на сервер вызывает создание поля ввода до вызова afterSaveCell. В примере clientArray, без отправки на сервер, afterSaveCell вызывается до того, как только что отредактированные данные ячейки преобразуются во входные данные. Мне нужно немного больше времени, чтобы создать правильный пример. Shawn 26.02.2011
  • @ Олег, я создал пример, который вы можете увидеть здесь. Если вы попытаетесь отредактировать столбцы Amount или Tax, а затем щелкнете по другому столбцу после редактирования, вновь переключенный на итог изменится на 0,00 вместо правильного итога. Это происходит потому, что ячейка, которую вы сейчас редактируете, возвращает элемент управления вводом getCell вместо значения ячейки. Происходит это из-за задержки с удаленным cellsubmit. Использование локального clientArray не вызывает этой проблемы. Shawn 26.02.2011

javascriptjqueryjqgrid

Ответы

Ответ 1 · рейтинг 11 · Oleg

Я вижу две проблемы в вашем коде. Первый более косметический, но правильное решение может многое упростить в будущем.

Первая проблема заключается в том, что вы вручную добавляете строку "ИТОГО" как часть данных сетки и вычисляете значения в строке внутри функции calculateTotal. Лучше использовать опцию footerrow:true, которая добавляет дополнительную строку внизу сетки, которая не смешивается с данными сетки. Для серверных данных вы можете использовать userdata часть ответа JSON или XML от сервера и использовать userDataOnFooter:true дополнительно для передачи данных из параметра userData jqGrid в строку нижнего колонтитула. В случае "локального" типа данных можно использовать метод footerData для установить (или получить) данные в нижнем колонтитуле. Кроме того, для вычисления суммы элементов можно использовать метод getCol. в колонке. Таким образом, ваша версия функции calculateTotal может быть переписана как

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

Теперь к вашей основной проблеме. Вы используете режим редактирования ячейки. Если функция calculateTotal (ваш оригинальный или мой упрощенный вариант) будет вызываться в момент, когда одна из ячеек 'сумма' или 'налог' находится в режиме редактирования, то calculateTotal будет прочитан фрагмент HTML с элементом <input> вместо строка с числом, и расчет не будет выполнен.

Я создал небольшую демонстрацию, которая вызывает calculateTotal каждую секунду. Поэтому, если вы щелкнете по любой ячейке в столбце "сумма" или "налог", вы увидите, что в строке нижнего колонтитула 0 будет отображаться как сумма. Таким образом, демо с cellsubmit:'clientArray' имеет ту же проблему, что и ваш исходный код с cellsubmit:'remote'.

Для решения проблемы можно использовать параметр data jqGrid при вычислении суммы:

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

Соответствующую фиксированную демонстрацию вы найдете здесь. В вашем окончательном коде вы можете удалить

setInterval(calculateTotal, 1000);

который я использовал только для демонстрации и обновлял нижний колонтитул только в обработчике событий afterSaveCell.

ОБНОВЛЕНО: если вы работаете с удаленными данными, вы не можете использовать параметр data. Таким образом, при необходимости нужно получить данные из элемента <input>. Я создал еще одно демо, демонстрирующее, как это можно сделать. Код calculateTotal будет длиннее:

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

Ответ 2 · рейтинг 1 · user1413147

Спасибо олег, решение для меня было применить и изменить то, что вы поставили

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

                 }

Ответ 3 · рейтинг 1 · Julia

Если вы просто хотите пересчитать общее количество, вы можете использовать триггер для перезагрузки сетки в событии afterSaveCell. Нравится:

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

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы