0

I used the following

ondblClickRow: function(){
    var row_id = $("#grid").getGridParam('selrow');
    jQuery('#grid').editRow(row_id, true);
}

from:

jqGrid Cell Editing - Double Click to Edit?

On double clicking I am able to get the alert but the EditRow function simply doesn't work.

-------Update-----------

This is the following code I use onclient side:-

function setJqGridParameters(parsedResult) {
            var lastSel;
            $('#list').jqGrid('GridUnload');
            $("#list").jqGrid({
                colModel: JSON.parse(parsedResult.colModel),
                colNames: JSON.parse(parsedResult.col),
                datatype: "jsonstring",
                datastr: JSON.parse(parsedResult.rows),
                jsonReader: {
                    repeatitems: false
                },
                gridview: true,
                rowNum: 10,
                cmTemplate: { title: false }, //, sortable: false },
                viewrecords: false,
                loadonce: true,
                loadui: 'block',
                height: 'auto',
                autowidth: true,
                loadtext: "Loading....",
                pgbuttons: false,
                pginput: false,
                pgtext: "",
                shrinkToFit: false,
                hoverrows: false,
                ondblClickRow: function (rowid) {
                    if (rowid && rowid !== lastSel) {
                        $('#list').restoreRow(lastSel);
                        lastSel = rowid;
                    }
                    $(this).jqGrid("editGridRow", rowid, {
                        keys: true,
                        addCaption: "Add Record",
                        editCaption: "Edit Record",
                        bSubmit: "Submit",
                        bCancel: "Cancel",
                        bClose: "Close",
                        saveData: "Data has been changed! Save changes?",
                        bYes: "Yes",
                        bNo: "No",
                        bExit: "Cancel",
                        width: window.screen.width / 3,
                        top: window.screen.height / 4,
                        left: window.screen.availWidth / 3,
                        editUrl: 'TypicalVolume.aspx/UpdateVolumeData',
                        beforeSubmit: function (postData, formid) {
                            //alert(JSON.stringify(postData));
                             PostDataToServer(postData);
                            $(".ui-widget-overlay").trigger('click');
                            $('#list').trigger('reloadGrid');
                            return false;
                        },
                        afterShowForm: function (formid) {
                            $("#COl1").focus();
                            //var cm = $(this).jqGrid('getColProp', 'Specialty');
                            //debugger;

                        }
                    });
                    // debugger;
                    //                    var grid = $('#list');
                    //                    var myRowData = grid.getRowData(rowid);
                    //                    grid.editRow(rowid, true);
                    //alert(myRowData['Specialty'] + ' ' + myRowData['SpecialtyName']);
                },
                loadComplete: function () {
                    fixPositionsOfFrozenDivs.call(this);
                },

                onSortCol: function (index, icol, sortorder) {
                    sortColumns(index, icol, sortorder);
                    return 'stop';
                }
            });
            resizeColumnHeader.call($("#list")[0]);
            $("#list").parents('div.ui-jqgrid-bdiv').css("max-height", $(window).height() - $('#pivotGridDiv').offset().top - 60);
            $("#list").jqGrid('setFrozenColumns');
            $("#list").triggerHandler("jqGridAfterGridComplete");

            fixPositionsOfFrozenDivs.call($("#list")[0]);
            $(".s-ico").hide();
            var cm = $("#list")[0].p.colModel;
            $.each($("#list")[0].grid.headers, function (index, value) {
                var cmi = cm[index], colName = cmi.name;
                if (cmi.sortable) {
                    $('div.ui-jqgrid-sortable', value.el).css({ cursor: "pointer" });
                }
            });
        }
        function PostDataToServer(Data) {
            $.ajax({
                type: "POST",
                data: "{" + "Data" + ":" + JSON.stringify(Data) + "}",
                url: "TypicalVolume.aspx/UpdateVolumeData",
                //data: JSON.stringify(obj),
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (result) {
                    if (result.d == "null") {
                        RedirectToLogin();
                    }
                    else {
                        SetValues(result);
                    }

                },
                error: function (result) {
                    $('#loadingIndicator').hide();
                    alert("getPageLoadData: " + result.responseText);
                    //RedirectToErrorPage();
                }
            });
        }

The SetJqGridParameters() function is called on pageload which sets all parameters of Jqgrid. I used the PostDataToServer() function to send data to server and write the Db Changes. Note:- If I remove the functionality I get an error of null reference in jqgrid.min.js.

----Server Code----

 [System.Web.Services.WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static string UpdateVolumeData(object Data)
{
    string WhereCondition1 = "",WhereCondition2="";
    List<string> UpdateStatements = new List<string>();
    Dictionary<string, string> data = new Dictionary<string, string>();
    data = ToDictionary(Data);
    foreach(KeyValuePair<string,string> entry in data)
    {
        if (entry.Key.ToString() == "MainCol1")
        {
            if (WhereCondition1 == "")
            {
                WhereCondition1 = WhereCondition1 + entry.Key.ToString() + "=" +"'"+ entry.Value.ToString()+"'";
            }
            else
            {
                WhereCondition1 = WhereCondition1 + "," + entry.Key.ToString() + "=" + "'"+entry.Value.ToString()+"'";
            }
        }
        else if (entry.Key.ToString() == "MainCol2")
        {
            if (WhereCondition2 == "")
            {
                WhereCondition2 = WhereCondition2 + entry.Key.ToString() + "=" +"'"+ entry.Value.ToString()+"'";
            }
            else
            {
                WhereCondition2 = WhereCondition2 + "," + entry.Key.ToString() + "=" +"'"+ entry.Value.ToString()+"'";
            }
        }
    }
    foreach (KeyValuePair<string, string> entry in data)
    {
        if (entry.Key.ToString() != "MainCol1" && entry.Key.ToString() != "MainCol2")
        {
            UpdateStatements.Add("Update TypicalVolume set TypicalVolume = " + entry.Value + " where Modality = '" + entry.Key + "' and " + WhereCondition1 + " and " + WhereCondition2);
        }
    }
    //JavaScriptSerializer serializer = new JavaScriptSerializer();
    //var data = serializer.Serialize(Data);
    string sqlstatements = string.Join(" ", UpdateStatements);
    SqlConnection conn = new SqlConnection(sqlConnectionString);
    conn.Open();
    SqlCommand cmd = new SqlCommand(sqlstatements, conn);
    cmd.ExecuteNonQuery();
    conn.Close();
    GridData gd = new GridData();
    gd = GetGridData();
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    return serializer.Serialize(gd);
}

 [System.Web.Services.WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static string GetDataBySearchCriteria()
{
    try
    {
        HttpContext.Current.Session["RoleID"] = 4;
        if (HttpContext.Current.Session["RoleID"] != null)
        {
            if (!CheckAuthorization()) // Redirect to error page if not authorized
            {
                throw new Exception("Un Authorized Acess");
            }
            else
            {
                HttpContext.Current.Session["TypicalVolumeSession"] = null; 
                if (HttpContext.Current.Session["TypicalVolumeSession"] != null)
                {

                    GridData gd = new GridData();
                    gd = HttpContext.Current.Session["TypicalVolumeSession"] as GridData;
                    JavaScriptSerializer serializer = new JavaScriptSerializer();
                    GridData gd1 = GetGridData();
                    return serializer.Serialize(gd1);
                }
                else
                {
                    HttpContext.Current.Session["TypicalVolumeSession"] = null;
                    GridData gridData = new GridData();
                    DataSet ds = SqlHelper.ExecuteDataset(sqlConnectionString, CommandType.StoredProcedure, "GetTypicalVolumes");

                   DataTable Datadt = ds.Tables[0];
                    //create col model for jqgrid
                    StringBuilder sbcol = new StringBuilder();
                    sbcol.Append("[");
                    foreach (DataColumn column in Datadt.Columns)
                    {
                        sbcol.Append("\"").Append(column.ColumnName).Append("\",");
                    }
                    sbcol.Remove(sbcol.Length - 1, 1).Append("]");
                    StringBuilder sbcolModel = new StringBuilder();
                    sbcolModel.Append("[");
                    string[] rowAreaFields = "MainCol1,MainCol2".Split(',');

                    //create rowdata for jqgrid
                    foreach (DataColumn column in Datadt.Columns)
                    {
                        if (rowAreaFields.Contains(column.ColumnName.Trim()))//apply style for row area fields
                        {
                            sbcolModel.Append("{\"name\":\"").Append(column.ColumnName.Trim()).Append("\",\"index\":\"").Append(column.ColumnName.Trim()).Append("\",\"classes\":\"colstyle\",\"align\":\"left\",\"editable\":true,\"editoptions\": { \"disabled\": \"disabled\" },\"sortable\":true,\"frozen\":true},");
                        }
                        else
                        {
                            sbcolModel.Append("{\"name\":\"").Append(column.ColumnName.Trim()).Append("\",\"index\":\"").Append(column.ColumnName.Trim()).Append("\",\"align\":\"right\",\"sortable\":false,\"editable\":true,\"width\":\"60px\"},");
                        }

                    }
                    sbcolModel.Remove(sbcolModel.Length - 1, 1);
                    sbcolModel.Append("]");


                    JavaScriptSerializer serializer = new JavaScriptSerializer();
                    List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
                    Dictionary<string, object> drow;
                    foreach (DataRow dr in Datadt.Rows)
                    {
                        drow = new Dictionary<string, object>();
                        foreach (DataColumn col in Datadt.Columns)
                        {
                            drow.Add(col.ColumnName, dr[col]);
                        }
                        rows.Add(drow);
                    }
                    StringBuilder sbjsonRows = new StringBuilder();
                    sbjsonRows.Append(serializer.Serialize(rows));

                    StringBuilder json = new StringBuilder();
                    json.Append("{").Append("\"rows\":").Append(sbjsonRows.ToString().Trim()).Append("}");
                    json.ToString();
                    gridData.col = sbcol.ToString();
                    gridData.colModel = sbcolModel.ToString();
                    gridData.rows = sbjsonRows.ToString().Trim();
                    return serializer.Serialize(gridData);//serialize and return to ajax method
                }
            }
        }
        else
        {
            return "null";//if session expired
        }
    }
    catch (Exception ex)
    {
        LogError(ex);
        throw;
    }
}

The code is in testing mode its still under development, the code is a template from other pages I have developed so it has used session but its not actually required as of now.

Requirement:- I have lots of data. So I would like to update the db and show the real data from db. Because other users might have updated it. So If possible I might want to load data in a lazy manner where I could load data for say 3 pages and then continue loading in the background(do I have such an option in jqgrid). In case its not feasible loading the whole data is ok.

Also I wish to make examples in C# and contribute them for other new users in as many ways as possible.So that users can find all documentation and help in one place. Please suggest how can I do that too.

For those who refer this:- This question originally started for editable rows. The first suggestion I got from @Oleg was sufficient. Later he found that my code was inconsistent because we used code from different jqgrid and also the server code was non standard (do not use those techniques).

To Beginners using jqgrid

Please make sure you are using the same jqgrid through out which will help you keep your code consistent. On the internet you can find different versions of jqgrid, so first make sure whether you want to you use free or commercial version, then go for the latest.

Community
  • 1
  • 1
  • 1
    Which version of jqGrid and which fork you use? Try to fix your code to the following: `ondblClickRow: function (rowid) { $(this).jqGrid("editRow", rowid, {keys: true}); }`. You should verify additionally that you set `editable: true` property in columns of `colModel` which you allow to edit. You can use `cmTemplate: { editable: true }` jqGrid option to set `editable: true` as default value for all columns. You still can use `editable: false` in some columns to make there non-editable. – Oleg Nov 03 '15 at 06:35
  • Hi Oleg, Great you are online. I use 4.6.0. I used both EditRow which is not taking me to edit mode.(I am yet to fix this by setting the editable property to true.) and I Used EditGridRow which gave me a popup but everything is undefined. Can you direct me to a sample where I can set up a template for editGridRow popup. Also inline edit is very welcome. Let me describe the functionality:- If I am using inline edit I need to show Save and cancel in the same row which is in edit mode. Please suggest how can I achieve this –  Nov 03 '15 at 06:37
  • I will be soon away for the whole day. Try the above changes. It should work. – Oleg Nov 03 '15 at 06:40
  • Thanks Oleg it worked for inline edit, I simply set the editable property to true from my server code where I am generating the data. –  Nov 03 '15 at 06:47
  • I have successfully created what I wanted. However I am not sure I understand how the grid reloads after every update I make. So I used the BeforeSubmit() event and called my own ajax function that would update the database, and I hide the edit form through code. Is there a better way to use custom db update and yet retain jqgrid functionality? –  Nov 04 '15 at 04:41
  • I'm not sure why you need to make seprate `ajax` call. What additional information you need to send to the server? [the part of documentation](http://www.trirand.com/jqgridwiki/doku.php?id=wiki:inline_editing#what_is_posted_to_the_server) describes what send `editRow` by default to the server. – Oleg Nov 04 '15 at 05:43
  • I used it because I am not sure about the functionality. I didn't know if it would show up the real server data(the updates could be done from different machines). So I used this method to call a method that populates the grid. On top that I did provide the editUrl, but it was throwing an error, so used this hack. Note:- I get data not directly from a table but by pivoting the data. So In the server how should I handle this editing functionality, do I have to send the whole data again. The records are more than 65000. Please suggest. –  Nov 04 '15 at 06:17
  • I asked you to post more **code** which shows what you do. Returns your server some additional data on saving the row? Do you want to reload the whole grid (or one page of data) after saving one row? Only if you describe **exactly** what you need to do I can show you how you can implement your requirements using the standard `editRow`. jqGrid have many options which allows to customize internal Ajax call, to include additional data which will be send to the server or to process the server response additionally. The best is the explanation of the possibilities on the example. – Oleg Nov 04 '15 at 06:24
  • Hi @Oleg I have updated the question. –  Nov 04 '15 at 07:00

1 Answers1

0

There are a lot of strange things in your code (on both server and client side). I don't want to rewrite your code. On the client side you just send the same postdata to the server. You just wrap the data in Data parameter and convert to JSON.

I just mention some clear problems in your code:

  • You place editUrl on the wrong place and you use wrong name of the option. The options of editGridRow should be url. The correct place of editurl parameter (!!! not editUrl !!!) is the option of jqGrid (on the same place where colModel, colModel and other).
  • To serialize the data posted duting editing to JSON one should use serializeRowData callback and ajaxRowOptions option if you use inline editing method editRow (see your original text). If you want to use editGridRow method instead (see UPDATED part of your question), then you need use serializeEditData instead of serializeRowData.
  • Call of inline editing method restoreRow inside of ondblClickRow callback have no sense in case of usage form editing method editGridRow. The usage of $('#list').trigger('reloadGrid'); inside of callback beforeSubmit of form editing have no sense because jqGrid reloads the data automatically after for editing. On the other side reloading of local data (you use datatype: "jsonstring") have no sences too.
  • you wrote in the comment to your question that you use jqGrid 4.6, but you use fixPositionsOfFrozenDivs method which exist only in free jqGrid. You should decide which fork of jqGrid you want to use and to use the corresponding options. In case of usage free jqGrid you could use new style of the options of form editing and inline editing (see the wiki article), which could make your code shorter and easy readable. On the other side the options will work only for free jqGrid. Thus it's important to know which fork of jqGrid you use and in which version.
  • I would recommend you to use parameters of SqlCommand and never construct the SQL statement directly as a string (see building of WhereCondition2 in your code). It's very dengarous.
  • You should never use manual serialization of output data in WebMethod: JavaScriptSerializer serializer = new JavaScriptSerializer(); return serializer.Serialize(gd);. It's wrong! ASP.NET makes JSON/XML serialization automatically based on Content-Type header of the HTTP request. The type of returned data should be object instead of string (public static string GetDataBySearchCriteria() need be replaced to public static object GetDataBySearchCriteria()). You should use return gd; instead of return serializer.Serialize(gd);. Your current server method serialize to JSON twice. The string returned by GetDataBySearchCriteria or by UpdateVolumeData will be serialized once more. Thus the server returns something like {"d": "{..., \"some string\"...}"} instead of {"d": {..., "some string"...}}. The usage of sbcolModel.Append("{\"name\":\"") and json.Append("{").Append("\"rows\":") is very bad too. Correct code should work only with objects. No manual conversion of JSON is required. Only because of that you need include additional call of JSON.parse or $.parseJSON. Typical $.ajax call converts JSON data to object internally and you works directly with object. It's probably the reason why you don't used datatype: "json" and jsonReader: {repeatitems: false}, ajaxGridOptions: { contentType: "application/json" }, serializeGridData: function (postData) { return JSON.stringify(postData); } and so on.

I can continue...

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Regarding the sql cmds you pointed out I am going to convert everything to proper Stored procedure calls once I get what I intend. But I can't take the risk of removing the sbcolModel functionality. It is a huge change in all my pages. I know I should not spit out html tags to DOM which will cause the page to appear stuck, but the code comes from different members who developed this earlier. So I had the option of templating but for the speed we could achieve even with this dirty code the client and team is happy. I shall use your tips to make it better ...thanks a lot. –  Nov 04 '15 at 11:32
  • I admit the code is highly insecure. When we first used the jqgrid, we had high pressure mounting on head because we transitioned from DevExpress Pivot Grid to Jqgrid and done all the pivoting on Sql side, and the number of columns is only known at run time(ColModel not known until client says his requirement). Also when we got to use the Jqgrid it was not 4.6.0. it was a subversion of version 3. Most importantly the problem with me is I only recently started using Github so I dont really understand the terminology used there. And yes we are intending to use the free version only –  Nov 04 '15 at 11:52
  • 1
    @Ganesh: You are welcome! jqGrid support pivot tables too. The functionality of `jqPivot` method of free jqGrid is described in [the wiki article](https://github.com/free-jqgrid/jqGrid/wiki/jqPivot-in-version-4.9). In any way your curent code conatins a lot of error. You should at least clean up the interface bettween the client (jqGrid) and the server (WebMethods). You can return from the mebmethod just `List`, use `loadonce: true` option of jqGrid or to use `jqPivot` to generate `colModel` dynamically. You will have very simple code of webmethods and clean JavaScript code. – Oleg Nov 04 '15 at 12:12
  • We have 10's of thousand's of records (>900000 approx) this data is accumulated per year and as we get to end of year we end up having huge amount of data, all that data is supposed to be pivoted by the control, it was really painful to wait that much of time so we decided to do the pivoting in sql server and were sending only few records as specified by pagesize dynamically and display using jqgrid. This gave us huge difference in speed. Also because we didn't want to load the browser with that huge data we came with that solution. Next time I post code I will make it OOP oriented & clean. –  Nov 04 '15 at 16:46
  • This is a BI application for internal use by a client. Thanks for the ColModel idea, this should be easily done. Will get on it. –  Nov 04 '15 at 16:47
  • Ok thanks. As of now the technique works for me. I am going to clean it up a little more. Thanks for all the effort. I have accepted the answer. –  Nov 04 '15 at 17:05
  • @Ganesh: You are welcome! I recommend you to go through your old questions and accept some answers. It will increase your reputation. – Oleg Nov 04 '15 at 18:43