0

In our application the user is able to edit multiple rows at the same time. When he clicks the save button all the rows are saved to DB, one by one.

The problem I have is that when a user fills in something wrong for example skipping a required field I want to cancel the saving from there and the user should be able to correct the error.

What I am missing in my solution is that I don't know how to disable a row in edit mode to original state after the row is saved with success. If I do restoreRow then the old values before editing are displayed.

My code (I keep my jqGrid in a variable called grid):

    function saveGrid() {
        var saveCollection = [];
        //Collect all rows in editmode, the rows to be saved.
        $.each(grid.getDataIDs(), function (index, id) {
            var row = grid.getInd(id, true);
            if (row !== false) {
                if ($(row).attr('editable') === '1') {
                    saveCollection.push(id);
                }
            }
        });

        //Function to save single row.
        function saveSingleRow(rowId) {
            var success = false;
            grid.saveRow(rowId, function () {
                //Row successfully saved.
                success = true;

                //Here I want to restore the row somehow but not with the old values.
            });

            //If everything worked out, save next row if there are any left.
            if (success) {
                saveCollection = $.grep(saveCollection, function (obj) {
                    return obj !== rowId;
                });

                if (saveCollection.length > 0) {
                    return saveSingleRow(saveCollection[0]);
                }
            }

            //If error or the last row, return success status.
            return success;
        }

        //Check if there are any rows in editmode, then begin to save each row.
        if (saveCollection.length > 0) {
            if (!saveSingleRow(saveCollection[0])) {
                //If something went wrong during saving cancel and return from this function.
                return;
            }
        }
        //Every row was successfully saved. Reload grid.
        grid.trigger('reloadGrid');
    }

As you can see, once an error occurs, will it be from the server or a validation error the save process stops and return false. But if this happens on lets say row number four then row one to three are already saved successfully but still in edit mode. The user will then have the feeling that these rows are not saved.

This is how I open up my rows for editing (inline editing). It happens when the user clicks the edit button in the toolbar:

var rows = $.grep(grid.getGridParam('selarrrow'), function () { return true; });
if (rows !== null && rows.length > 0) {
    $.each(rows, function (i1, gr) {
        if (gr !== null) {
           grid.editRow(gr, false);
        }
    });
}

So is there a kind of "de-edit" function? I can't come up with a better main solution right now. Is there a way to check if there are any validation errors before starting the save process? Then I could check that and after that send all my rows to the server and save them within a transaction.

Appreciates any help! Thank you.

UPDATED The solution is that there is no function that lock rows again after saving. This should be done automatically when saves are successful. In this case the problem is that when adding the callback function that runs after the save comes back to the client successfully you have to return true for this to happen. So this is what was missing (the statement at the bottom: return true;):

grid.saveRow(rowId, function () {
                //Row successfully saved.
                success = true;

                //Here I want to restore the row somehow but not with the old values.
                return true;
            });
John
  • 2,043
  • 5
  • 28
  • 49

1 Answers1

1

It seems to me you should just add "not-editable-row" class to the row (<tr> element) after successful saving of the changes. See the answer for details and the demo.

UPDATED based on the discussion from comments: What you describe shows me that saving the rows works incorrect in your demo. After successful saving the saveRow closes the editing mode of the saved row. I created the demo which do what you describe, but uses the local editing only. In case of saving the data on the server all should work exactly in the same way.

In the comment you wrote "the grid is locked for editing if another user is currently in edit mode on another computer". In case of web application the locking of data in the database is a bad practice in my opinion. In breaking of connection to the client or in case of other errors you can easy have locking data in the database and no client connected. One use typically optimistic concurrency control instead. See here and here for details.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • No unfortunately it didn't work. I am not sure I make my problem clear. I edited the post and added the code for how I open up my rows for editing. The rows are open in edit mode all the time while the user is editing the data. If the save is successful then I do reload grid and the rows goes back to their original read-only state. But if there is an error somewhere in the save process I need to have the rows successfully saved to go back to original state. Applying the class didn't solve the problem and I didn't thought it would. – John Aug 02 '11 at 14:07
  • For it to work then element has to listen to an event which fires when css classes are added. Check if the class is "not-editable-row" and if so, manipulate the grid. I believe I am looking for a method or I could probably iterate over the cells, remove the input element and add a span instead with the same value. But before I start to hack I am searching for the built in functionality if it exists. – John Aug 02 '11 at 14:07
  • @John: Sorry, but I sill not sure that I understand you correct. To abort the inline editing of a row you can use [restoreRow](http://www.trirand.com/jqgridwiki/doku.php?id=wiki:inline_editing#restorerow). To prevent the row be editing (till reloading of the grid) one can use "not-editable-row" class. You asked "how to disable a row in edit mode to original state after the row is saved with success". Then you wrote that "I need to have the rows successfully saved to go back to original state" which I can't understand. How you save the rows? – Oleg Aug 02 '11 at 14:34
  • @Jonh: jqGrid hold the old state **only for one row**. If you save **one row at the time** without creating one transaction **you can't go to the previous state** because nobody hold the old state. Moreover at the next attept **another rows** can be modified by some other person from the another computer. Exactly because of problems with concurency errors or other errors jqGrid have no possibility to save multiple rows at the time. – Oleg Aug 02 '11 at 14:35
  • @Jonh: At the first time it seems interesting to save many rows at once, but if you think about possible errors and the error corrections you see that using the "batch" saving you created much more serious problem as you had before. I personally **never** use the saving of multiple rows and I don't recommend other to do this. – Oleg Aug 02 '11 at 14:36
  • Okay. I'll try to explain again :) The workflow is like this: The user sees the grid and then selects which rows to be edited in the grid (multiselect = true) and then clicks the edit button. I open up the rows for editing by calling grid.editRow(rowId) for all selected rows. What happens now are that the -elements instead of only text value now has a child element which is an input where the user can edit the cell value. When the user is done editing she clicks the save button. – John Aug 03 '11 at 10:59
  • Now I collect all the rows which are open for edit in an array and then iterates over that array and save each row one by one by calling grid.saveRow(rowId). When the save is finished all the rows still are open for editing (the input elements are still there) therefor I call reloadGrid to "close them". When I look at the Row editing -> Basic Example in the jqGrid examples (http://www.trirand.com/blog/jqgrid/jqgrid.html) I can see that they don't call reloadGrid. The saved row goes back to back read-only state after saving by itself. This is not happening for me. – John Aug 03 '11 at 10:59
  • For me it is important to be able to save multiple rows. When you enter a grid in our application the grid is locked for editing if another user is currently in edit mode on another computer. So we take care of that before you start to edit and save rows. Only one user can edit the same type of grid at one time. I need to find a way to "close" the rows for editing when they have been saved. Now I have to call reloadGrid for that to happen. – John Aug 03 '11 at 11:00
  • @John: I updated my answer and created [the demo](http://www.ok-soft-gmbh.com/jqGrid/SimpleLocalGridWithInlineEditingMultiline.htm) for you which shows how should `saveRow` work. – Oleg Aug 03 '11 at 12:16
  • Thank you very much for your time and help. I found the bug. I copied your demo (thanks again) and pasted into my solution. I changed from local editing to post the rows to a webservice with json like my case. Everything worked correctly until I added the successfunc as a callback to the saveRow method. The bug was that I didn't returned anything from that function so it returned undefined as default. When I read the documentation again it said: "Depending on the data from server; this function should return true or false.". – John Aug 03 '11 at 14:31
  • About the possible concurrency problems we have set a short time which the user can be inactive when editing a grid or form. So if a user disconnects the lock will only block the other user for this short time set to something like 10-20 minutes I believe. We haven't had any problem so far but I know what you are saying and optimistic concurrency is probably a better solution but not a priority right now. – John Aug 03 '11 at 14:35
  • @John: You are welcome! Which database you use? If you develop in C# you use probably Microsoft SQL server? – Oleg Aug 03 '11 at 14:38
  • Yes. I am developing a business application in a team. We use Javascript/Ajax, C# and Microsoft SQL. – John Aug 03 '11 at 14:44
  • @John: I use also Microsoft SQL Server. It has very helpful `rowversion` datatype. If you add in all tables which can be changed by users additional column like `RowUpdateTimeStamp rowversion NOT NULL` the column will be maintained by SQL automatically. If somebody change some data in the row the value of the `RowUpdateTimeStamp` column (you can choose another name) will be increased. In the way you can easy detect concurrency errors and implement optimistic concurrency control. – Oleg Aug 03 '11 at 14:54
  • My main problem is solved. The reason I didn't mark your answer as accepted is that I didn't think that answer really was the correct answer, but without your help, demo and input I wouldn't have solved that fast though. I tried to edit your post and add the exact answer to the problem but that edit never went through :(. I mark your answer as accepted anyway and any one who reads this post has to find the solution here in the comments field. Thank you about the tip of MSSQL, I did know about the rowversion (I am certified T-SQL, can you believe it..). – John Aug 03 '11 at 20:05
  • Keep up the good work with sharing your knowledge about jqGrid! – John Aug 03 '11 at 20:05
  • @John: You are welcome! If you have any suggestion for editing you can post this at the bottom of **your answer**. I will cut it and move to my answer. Just post me a comment to notify that you have it. I try to have answers so that it could help other people, so if you have any ideas to improve the text it would be very good. – Oleg Aug 03 '11 at 20:11
  • Now I edited my post with "the answer". Feel free to copy and paste it down to your post instead. – John Aug 04 '11 at 06:01
  • @John: OK! It looks good now and nothing need be done more. I hope it will help other people who have the same problem. – Oleg Aug 04 '11 at 08:45