jqGrid - 新行的唯一ID [英] jqGrid - Unique ID for new row

查看:148
本文介绍了jqGrid - 新行的唯一ID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将一个唯一ID设置为我添加到jqGrid的新行。我使用免费的jqGrid 4.11.0,服务器端的java rest服务和数据库的MS SQL。

I am trying to asign a unique ID to the new rows i add to my jqGrid. I use free jqGrid 4.11.0, a java rest service for the server side and MS SQL for databases.

inlineEditing: {

    ajaxSaveOptions: { contentType: "application/json" },
    serializeSaveData: function (postData) {

        var idArray = grid.getCol('id');
        var count = 0;
        var k = 1;

            while(postData.id.search('jqg') != '-1'){

                for(var i =0 ; i<idArray.length;i++){

                    if(k == idArray[i]){
                        count++;
                    }
                    if(count == 0){

                        postData.id = k  ;
                        break;                              
                    }
                }                       
                k++;
            }               
        return JSON.stringify(postData);
    }
}

我注意到jqGrid给出的默认ID是jqg +一个号码。有关如何制作当前未在任何数据库记录中使用的唯一ID的任何建议?我应该从服务器端执行此操作还是可以在jqGrid代码中执行此操作?

I noticed the default ID given by jqGrid is jqg + a number. Any suggestions on how i could make a unique ID thats not currently in use on any of the database records? Should i do this from the server side or it can be made in the jqGrid code?

在晚上的某个时刻,此代码有点工作并继续提供id 7到所有新行[即使它应该继续增加]。经过一些更改[无法记住更改]后,每次单击保存将新行提交到服务器时,页面会冻结并且chrome建议我应该终止该过程。

At some point in the evening, this code was kind of working and kept on giving id 7 to all new rows [even though it should have kept on increasing]. After some changes[cant remember what changes], every time i click save to submit the new row to the server, the page freezes and chrome suggest i should kill the process.

请让我知道如果我应该添加更多信息。

Please let me know what and if i should add more information.

Edit1:

$(function () {

var grid = $('#grid'),
    checkboxEditOptionEvents = [

        {type : 'click', data: {'Yes': 'Yes'}, fn: function (e, id) {
            var checkboxCol = grid.getCol('sefDepartament'),
                ids = grid.jqGrid('getDataIDs'),
                numberOfCheckedBoxes = [],
                k;

            for (k = 0; k < ids.length; k++) {
                    if(checkboxCol[k] == 'Yes'){
                        numberOfCheckedBoxes.push(checkboxCol[k]);
                        if (numberOfCheckedBoxes.length == 1){
                            alert('Please deselect the other checked box first');
                            $(this).prop("checked",false);
                            numberOfCheckedBoxes = 0;
                        }
                    }
        }
    }}];

var experienceFunction = function(cellvalue, options ,rowObject){

            var joinYearVar =  rowObject.joinYear,
             YY = joinYearVar.slice(0,4),
             MM = joinYearVar.slice(5,7),
             DD= joinYearVar.slice(8,11);

            return moment("\"" +YY+MM+DD+"\"" , "YYYYMMDD").fromNow();

};

var checkboxFormatFunc = function(cellvalue, options ,rowObject){
    if(cellvalue == 'Yes'){
        return 'Yes';
    }
    return 'No';
};

var  afterSaveFunction =   function(id){

            var prenumeVar = grid.getCell(id, 'prenume').trim(),
                numeVar = grid.getCell(id,'nume').trim(),
                usernameVar =  numeVar +'.'+ prenumeVar,
                emailVar = usernameVar + '@test.com';
            usernameVar =usernameVar.replace(/\s/g , '').trim();
            emailVar = emailVar.replace(/\s/g , '');

            grid.setCell(id, 'username', usernameVar);
            grid.setCell(id, 'email', emailVar);

};

var colModelSettings = [

    {name:'id', label:'id',key: true,hidden: true, width:10,sorttype:'number',editable: false},     
    {name:'nume',label:'Nume',width:90, align: 'center',editable:true,searchoptions: {sopt: ['eq','bw','ew','cn']}, editrules:{required:true}, editoptions: {defaultValue: ' '},formatter: 'text'},
    {name:'prenume',label:'Prenume',width:100,editable:true,searchoptions: {sopt: ['eq','bw','ew','cn']},align: 'center',editrules:{required:true},editoptions: {defaultValue: ' '},formatter: 'text'},
    {name:'username',label:'Username',searchoptions: {sopt: ['eq','bw','ew','cn']},width:125,align: 'center'  },
    {name:'email',label:'Email',width:135,searchoptions: {sopt: ['eq','bw','ew','cn']},align: 'center'},
    {name:'sefDepartament',label:'Sef Departament',width:90,editable:true,align: 'center', stype:"select", searchoptions:{sopt: ['eq','ne'],value: "Yes:Yes;No:No"},formatter: checkboxFormatFunc,edittype:'checkbox',editoptions: { dataEvents: checkboxEditOptionEvents,value:'Yes:No', defaultValue: 'No' }},
    {name:'position',label:'Position',editable:true,stype: 'select',formatter: 'select',searchoptions: {sopt: ['eq','ne'],value: ' : ;position 1:position 1;position 2:position 2;position 3:position 3;position 4:position 4;position 5:position 5'},
    align: 'center',edittype:'select',editoptions:{defaultvalue: 'P0: ',value: ' : ;position 1:position 1;position 2:position 2;position 3:position 3;position 4:position 4;position 5:position 5'},width: 75},

    {name:'joinYear',label:'Join Year',formatter:'date', formatoptions: {newformat:'d-m-Y'}, datefmt: 'dd-mm-yyyy', editable:true,searchtype: 'datepicker',align: 'center',width: 70,
    searchoptions:{dateFormat:'dd-mm-yy',dataInit: function (elem){
        $(elem).datepicker({ showButtonPanel: true, dateFormat: 'yy-mm-dd'});},sopt: ['eq','ne']},

    editoptions:{size:20,defaultValue: ' ',dataInit: function (elem) {

        $(elem).datepicker({ showButtonPanel: true, dateFormat: 'dd-mm-yy'});
    }}},

    {name:'experience', label:'Experience', formatter: experienceFunction, searchoptions:{sopt: ['eq','bw','ew','cn']}, editable:'hidden', editoptions:{defaultValue: ' '},align: 'center',width: 60},
    {name:'actiuni',label: 'Actiuni',formatter: 'actions', formatoptions: {afterSave:afterSaveFunction},editable: false,sortable: false,search: false,width: 20 }
    ];

grid.jqGrid({

    pager: '#pager', 
    url: "/RestWithDatabaseConnection/rest/fetchData",
    editurl:'/RestWithDatabaseConnection/rest/update',
    datatype: "json",
    height: 250,    
    viewrecords: true,
    scrollOffset:0,
    sortorder: 'asc', 
    caption:'Employee List' ,
    autowidth: true,
    colModel: colModelSettings,
    beforeSelectRow : function(id){ 

                        var idsArray = grid.jqGrid('getDataIDs');
                        var i;
                        for(i=0;i<idsArray.length;i++){
                            if($('#'+idsArray[i]).is('[editable="1"]') ){
                            grid.editRow(idsArray[i],true);
                            return false;
                            }
                        }   
                        return true;
                    },

    inlineEditing: {

        ajaxSaveOptions: { contentType: "application/json" },
        serializeSaveData: function (postData) {

            var idArray = grid.getCol('id');
            var count = 0;
            var k = 1;

                while(postData.id.search('jqg') != '-1'){

                    for(var i =0 ; i<idArray.length;i++){

                        if(k == idArray[i]){

                            count++;
                        }
                        if(count == 0){

                            postData.id = k  ;
                            break;
                        }
                    }
                    k++;
                }

            return JSON.stringify(postData);
        }
    }
});


grid.jqGrid('navGrid', '#pager', {edit:false, add:false, delete:true, save:false, cancel:false, search:true, searchtext: 'Search', refresh:true},

        {},{},{     
                url: '/RestWithDatabaseConnection/rest/delete',
                mtype: 'DELETE',
                reloadAfterSubmit: true,
                ajaxDelOptions: {
                    contentType: "application/json",
                },
                serializeDelData: function(postdata) {

                    return JSON.stringify(postdata);

            }},{},{},{},{} );

grid.jqGrid('inlineNav','#pager',
{
    edit:true,
    edittext: 'Edit',
    save:true,
    savetext: 'Save',
    add:true,
    cancel: true,
    canceltext: 'Cancel',
    cancelicon: 'ui-icon-cancel',
    addicon:'ui-icon-plus',
    addtext: 'Add',
    addedrow: 'last',
    addParams: {

        position: 'last',
        addRowParams: { 

            aftersavefunc : afterSaveFunction,
            keys: true,
        }
            },
    editParams:{

        url: '/RestWithDatabaseConnection/rest/update',
        mtype : "POST",
        keys: true,
        aftersavefunc : afterSaveFunction,
    }
})})

Edit2 - 服务器对fetchData的响应:

Edit2 - Server Responce to fetchData :

[{"id":"3","nume":"Aladin","prenume":"Zoro","username":"Aladin.Zoro","email":"Aladin.Zoro@test.com","sefDepartament":"Yes","position":"position 4","joinYear":"2015-11-08","experience":"2 months"},

{"id":"2","nume":"Harap","prenume":"Alb","username":"Harap.Alb","email":"Harap.Alb@test.com","sefDepartament":"No","position":"position 1","joinYear":"2016-01-03","experience":"9 days  "},

{"id":"4","nume":"Don","prenume":"Homa","username":"Don.Homa","email":"Don.Homa@test.com","sefDepartament":"No","position":"position 4","joinYear":"2015-09-06","experience":"4 months"},

{"id":"5","nume":"Dorel","prenume":"Gigel","username":"Dorel.Gigel","email":"Dorel.Gigel@test.com","sefDepartament":"No","position":"position 4","joinYear":"2016-01-10","experience":"2 days"},

{"id":"1","nume":"Ivan","prenume":"Stefan","username":"Ivan.Stefan","email":"Ivan.Stefan@test.com","sefDepartament":"No","position":"position 2","joinYear":"2016-01-10","experience":"2 days"}]


推荐答案

以下是一些建议解决您的主要问题并改进您发布的JavaScript代码。

Below are some advises to solve your main problem and to improve the JavaScript code which you posted.

首先,需要生成新的rowid 本地用于本地编辑方案。如果将数据保存在数据库的后端,则应在服务器上生成新的rowid 。典型的实现包括在每个表中将 PRIMARY KEY 定义为 int IDENTITY 。它使id独特且固定。删除某些行并创建新行永远不会被解释为编辑旧行,因为新行将始终获得新的id,这在以前从未使用过(在表中)。

First of all, the generation of new rowids locally is required for local editing scenario. One should generate the new rowids on the server in case of saving the data on the backend in the database. Typical implementation consist on having PRIMARY KEY defined as int IDENTITY in every table. It makes the ids unique and fixed. Deleting of some row and creating the new one will never be interpreted as editing of the old row because the new row will get always new id, which was never used before (in the table).

要利用服务器端生成的ID ,我们有两个主要选择:

To have advantage of ids generated on the server side one have two main choices:


  1. 每次添加行操作后重新加载网格。

  2. 在编辑时扩展与服务器的通信,以便服务器将在数据库表中生成的新id返回给jqGrid。在服务器上成功创建行之后,可以使用 aftersavefunc 回调(仅用于添加新行)来更新rowid。 RESTful服务的许多标准实现都在Add或Edit上返回完整行数据包含id。可以使用 aftersavefunc 回调中的数据,并使用类似 $(#+ rowid).attr(id,newRowid); 更新新行。它在一些额外的列中保存了id(就像你使用隐藏的 id 列)然后另外应该使用 setCell 方法更新单元格。

  1. reloading the grid after every Add row operation.
  2. extending the communication with the server on editing so, that the server returns new id, generated in the database table, back to jqGrid. One can use aftersavefunc callback (for Add new row only) for updating the rowid after successful creating the row on the server. Many standard implementations of RESTful services returns back full row data inclusive id on both Add or Edit. One can use the data inside of aftersavefunc callback and use something like $("#" + rowid).attr("id", newRowid); to update the new row. It one saved the id in some additional columns (like you use hidden id column) then one should use setCell method additionally to update the cell too.

首选是最简单的,我建议你先实现它。只有重新加载网格不能满足一个接一个地添加许多行的用户,那么你应该多写一些代码并实现第二个场景。

The first choice is the mostly simple and I would recommend you to implement it first of all. Only if reloading of the grid will not satisfy the users, who add many rows one after another, then you should write a little more code and to implement the second scenario.

您当前的代码使用 inlineNav 进行添加和编辑操作,使用内联编辑实现,方法 navGrid 进行删除操作,使用表单编辑实现。表单编辑(包括Delete)默认使用 reloadAfterSubmit:true 选项。这意味着在删除每一行后,网格将从服务器重新加载(来自 url:/ RestWithDatabaseConnection / rest / fetchData)。您可以通过将 afterSaveFunction 替换为以下内容来解决您的主要问题:

You current code use inlineNav for Add and Edit operations, implemented using inline editing, and the method navGrid for Delete operation, implemented using form editing. The form editing, inclusive Delete, uses reloadAfterSubmit: true option by default. It means that the grid will be reloaded from the server (from url: "/RestWithDatabaseConnection/rest/fetchData") after deleting of every row. You can solve your main problem by replacing afterSaveFunction to the following:

var afterSaveFunction = function () {
        $(this).trigger("reloadGrid", [{current: true, fromServer: true}]);
    };

保持当前选择的选项当前重新加载后,选项 fromServer:true 只有在你另外使用 loadonce:true 选项的情况下才有意义。你可以使用 reloadGridOptions:{fromServer:true} 选项 navGrid 来强制重新加载数据服务器,单击导航栏的刷新/重新加载按钮。如果你没有那么多你需要在网格中显示的数据(例如少于1000行),那么建议采用这种行为。

The option current to hold the current selection after reloading and the option fromServer: true have sense only in case if you use loadonce: true option additionally. You can just use reloadGridOptions: {fromServer: true} option of navGrid to force reloading the data from the server on click on the Refresh/Reload button of the navigator bar. If you have not so much data which you need to display in the grid (for example less as 1000 of rows) then such behavior would be recommended.

一些更常见的建议为了改善您的代码:

Some more common advices to you to improve your code:

您可以考虑使用 height:auto而不是 height:250 并通过指定 rowNum 值来管理网格的最大高度。在这种情况下,将不需要选项 scrollOffset:0

You can consider to use height: "auto" instead of height: 250 and to manage the maximal height of the grid by specifying rowNum value. The option scrollOffset: 0 will be unneeded in the case.

从服务器返回的数据格式看起来所以,你没有实现服务器端分页,排序和过滤。您应该使用 loadonce:true forceClientSorting:true 选项。 loadonce:true 通知jqGrid在内部数据中保存所有本地服务器返回的数据参数。您可以随时使用 $('#grid')。jqGrid(getGridParam,data)访问数组。 rowNum (默认值为20)的值将用于本地分页。 sortname sortorder 将用于本地排序。您将使用的搜索对话框(由 navGrid 添加)或过滤器工具栏(由 filterToolbar 添加)本地搜索/过滤。它简化了服务器代码,从用户的角度提高了网格性能,并简化了服务器和客户端之间的接口。你可以在服务器上使用经典的RESTful接口而不需要任何扩展。

The format of the data returned from the server looks so, that you don't implemented server side paging, sorting and filtering. You should use loadonce: true and forceClientSorting: true options. The loadonce: true informs jqGrid to save all the data returned from the server locally in internal data parameter. You can any time access the array by usage $('#grid').jqGrid("getGridParam", "data"). The value of rowNum (the default value is 20) will be used for local paging. The sortname and the sortorder will be used for local sorting. And you will use searching dialog (added by navGrid) or the filter toolbar (added by filterToolbar) for local searching/filtering. It simplify the server code, improve the performance of the grid from the user's point of view, and simplifies the interface between the server and the client. You can use the classical RESTful interface on the server without any extensions.

另一句话:我建议你删除不需要的隐藏 id column( name:'id',label:'id',key:true,hidden:true,... )。有关rowid的信息将保存在行的 id 属性中(< tr> 元素)和一个don我需要在每行的隐藏< td> 元素中保留重复信息。

Another remark: I'd recommend you to remove unneeded hidden id column (name:'id', label:'id', key: true, hidden: true, ...). The information about the rowid will be saved in id attribute of the rows (<tr> element) and one don't need to hold duplicate information in the hidden <td> element in every row.

有很多代码的其他部分,可以改进。例如,您在服务器端使用的DELETE操作似乎很奇怪。您使用 mtype:'DELETE',但是您将请求的 body 中已删除行的ID发送到服务器,而不是将其附加到服务器URL。对应于标准,HTTP DELETE应包含无正文。您可以使用jqGrid选项 formDeleting 指定所有删除选项,并可以将 url 参数定义为函数:

There are many other parts of your code, which could be improved. For example the DELETE operation which you use on the server side seems be strange. You use mtype: 'DELETE', but you send the id of deleted row inside of body of the request to the server instead of appending it to the URL. Corresponds to the standards, the HTTP DELETE should contains no body. You can use jqGrid option formDeleting to specify all Delete options and you can define url parameter as function:

formDeleting: {
    mtype: "DELETE",
    url: function (rowid) {
        return "/RestWithDatabaseConnection/rest/delete/" + rowid;
    },
    ajaxDelOptions: { contentType: "application/json" },
    serializeDelData: function () {
        return "";
    }
}

您需要修改服务器代码 / RestWithDatabaseConnection / rest / delete / 使用相同的通信协议并从URL中获取已删除的ID。

You need of cause modify your server code of /RestWithDatabaseConnection/rest/delete/ to use the same communication protocol and to get the id of deleted from from the URL.

您可以使用免费jqGrid的 navOptions 参数来指定 navGrid的选项

You can use navOptions parameter of free jqGrid to specify the options of navGrid:

navOptions: { edit: false, add: false }

searchtext:'搜索'以及您使用的其他选项似乎都有默认值,我在那里删除了。)

(searchtext: 'Search' and other options which you use seems to have default values and I removed there).

为了更接近REST标准,可以使用HTTP PUT操作进行行编辑,使用HTTP POST进行添加新行。您应该为后端的两个操作实现不同的入口点。您已经使用 / RestWithDatabaseConnection / rest / update ,您可以实现 / RestWithDatabaseConnection / rest / create 来添加新行。您可以使用以下 inlineEditing 更改来实现方案:

To be closer to REST standards one can use HTTP PUT operation for row editing and HTTP POST for adding new rows. You should implement different entry points for both operation on the backend. You use /RestWithDatabaseConnection/rest/update already and you can implement /RestWithDatabaseConnection/rest/create for adding new rows. You can use the following inlineEditing changes for example to implement the scenario:

inlineNavOptions: { add: true, edit: true },
inlineEditing: {
    url: function (id, editOrAdd) {
        return "/RestWithDatabaseConnection/rest/" +
            (editOrAdd === "edit" ? "update" : "create");
    },
    mtype: function (editOrAdd) {
        return editOrAdd === "edit" ? "PUT" : "POST";
    },
    keys: true,
    serializeSaveData: function (postData) {
        return JSON.stringify(dataToSend);
    },
    aftersavefunc: function () {
        $(this).trigger("reloadGrid", [{current: true, fromServer: true}]);
    },
    addParams: {
        addRowParams: {
            position: "last",
            serializeSaveData: function (postData) {
                var dataToSend = $.extend({}, postData);
                // don't send any id in case of creating new row
                // or to send `0`:
                delete dataToSend.id; // or dataToSend.id = 0; 
                return JSON.stringify(dataToSend);
            }
        }
    }
}

这篇关于jqGrid - 新行的唯一ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆