Inline Editing With The WebGrid

4.57 (35 votes)

Unlike the Web Forms GridView control, the Web Pages WebGrid doesn't offer anything by way of inline editing capability. This article looks at one approach to solving that requirement through the addition of a sprinkling of jQuery.

I have already looked at one approach to editing with the WebGrid, which involved invoking a jQuery dialog that contained a form. The approach covered in this article differs in that each row of data is presented as read-only, but converted to an editable format within the WebGrid so that the user doesn't have to leave the WebGrid to make their alterations:

Inline Editing With The WebGrid

The key to this approach is to populate the grid with both readonly and editable versions of the data, then to use the jQuery toggle command to swap between the two presentations on a line-by-line basis. So I need data prepared for dropdown lists when the page first loads as well as data to be displayed in read-only mode:

    var db = Database.Open("Books"); 
    var books = db.Query(@"SELECT b.BookId, b.Title, b.ISBN, b.AuthorId, b.CategoryId, 
                            a.FirstName + ' ' + a.LastName AS AuthorName, c.Category  
                            FROM Books b INNER JOIN Authors a 
                            ON b.AuthorId = a.AuthorId  
                            INNER JOIN Categories c 
                            ON b.CategoryId = c.CategoryId 
                            ORDER BY b.BookId DESC");
    var categories = db.Query("SELECT CategoryId, Category FROM Categories")
                        .Select(category => new SelectListItem {
                            Value = category.CategoryId.ToString(), 
                            Text = category.Category
    var authors = db.Query("SELECT AuthorId, FirstName + ' ' + LastName AS AuthorName FROM Authors")
                        .Select(author => new SelectListItem {
                            Value = author.AuthorId.ToString(), 
                            Text = author.AuthorName
    var grid = new WebGrid(books);                                                         

The code gets three sets of data - the books details that I want to display, the collection of categories that the books can belong to and the authors that the books have been written by. The last two sets of data are converted to Enumerable<SlectListItem>. This is so that they can be plugged directly into Html.DropDownList helpers. Finally, the books data is passed into a WebGrid. Here is the code for the grid:

    tableStyle : "table",
    alternatingRowStyle : "alternate",
    selectedRowStyle: "selected",
    headerStyle : "header", 
    columns : grid.Columns(
                    style: "col1", 
                    format: @<text>
                                <button class="edit-book display-mode" id="@item.BookId">Edit</button>
                                <button class="save-book edit-mode" id="@item.BookId">Save</button>
                    style: "col2",
                    format: @<text>
                                <span id="title" class="display-mode">@item.Title</span>
                                @Html.TextBox("Title", item.Title, new {@class="edit-mode", size = 45})
                    header : "Author",
                    style: "col3",
                    format: @<text>
                                <span id="authorname" class="display-mode">@item.AuthorName</span>
                                @Html.DropDownList("AuthorId", null, authors, item.AuthorId, new {@class="edit-mode"})
                    style: "col4",
                    format: @<text>
                                <span id="category" class="display-mode">@item.Category</span>
                                @Html.DropDownList("CategoryId", null, categories, item.CategoryId, new {@class="edit-mode"})
                    style: "col5",
                    format: @<text>
                                <span id="isbn" class="display-mode">@item.ISBN</span>
                                @Html.TextBox("ISBN", item.ISBN, new {@class="edit-mode", size = 20})

The main thing to take note of is that there are two items in each of the cells. In most of them, there is a span that holds the item for display, and a form element for editing the item. As I mentioned earlier, I am using the Html form helpers mainly because they require a lot less code than HTML itself. All items designed for display are given the CSS class "display-mode". The form fields have the CSS class of "edit-mode" applied to them. Both of the buttons in the first column are given two CSS classes.

The next part of the jigsaw is the jQuery code that manages switching between the two modes:

    $(function () {
        $('.edit-book').on('click', function () {
            var tr = $(this).parents('tr:first');
            tr.find('.edit-mode, .display-mode').toggle();
        $('.save-book').on('click', function () {
            var tr = $(this).parents('tr:first');
            var bookId = $(this).prop('id');
            var title = tr.find('#Title').val();
            var authorId = tr.find('#AuthorId').val();
            var categoryId = tr.find('#CategoryId').val();
            var isbn = tr.find('#ISBN').val();
                { BookId: bookId, Title: title, AuthorId: authorId, CategoryId: categoryId, ISBN: isbn },
                function (book) {
                }, "json");
            tr.find('.edit-mode, .display-mode').toggle();

The first thing this script does is to hide all items with a CSS class of edit-mode resulting in all of the form fields and the Save button being hidden. An event handler is hooked up to the click event of the Edit button. This gets a reference to the table row that the button is in, and then toggles the visibility of all items within it that have a CSS class of edit-mode and display-mode. Since all edit-mode items were hidden at the outset, they now become visible, and all display items are hidden.

The next section of jQuery code applies an event handler to the click event of the Save button. Like the previous event handler, it obtains a reference the the current row, and then obtains values from the form fields and dropdowns as well as the ID of the current item from the Save button itself (which has been applied to its id attribute). It then packages these values and posts them to a page called EditBook.cshtml. Notice the absence of <form> tags in the code; jQuery takes care of constructing the POST request. Then it takes the data that the EditBook page returns and uses that to update the spans containing the displayed data. Finally, the edit-mode and display-mode items in the current row have their visibility toggled once again.

Here is the code for the EditBook.cshtml file:

    var bookId = Request["BookId"];
    var title = Request["Title"]; 
    var authorId = Request["AuthorId"];
    var categoryId = Request["CategoryId"];
    var isbn = Request["ISBN"];
    var db = Database.Open("Books");
    var sql = "UPDATE Books SET Title = @0, AuthorId = @1, CategoryId = @2, ISBN = @3 WHERE BookId = @4";
    db.Execute(sql, title, authorId, categoryId, isbn, bookId);
    sql = @"SELECT b.Title, b.ISBN,  a.FirstName + ' ' + a.LastName AS AuthorName, c.Category  
            FROM Books b INNER JOIN Authors a ON b.AuthorId = a.AuthorId  
            INNER JOIN Categories c ON b.CategoryId = c.CategoryId 
            WHERE BookId = @0";
    var result = db.QuerySingle(sql, bookId);
    Json.Write(result, Response.Output);

It takes the values from the Request collection, and uses them to update the database table. Then it retrieves the data back from the database suitably shaped for display. Finally, the Json helper is used to send that data back to the calling code for consumption.

The code for this article is available at GitHub.


You might also like...

Date Posted:
Last Updated:
Posted by:
Total Views to date: 71350


- Nasir Raza

Great break through, I was looking this kind of code in web pages. Keep it up.
However, code for the article is not available. I think you have yet to publish it...

- Mike

Apologies, the download link should work now.

- Nasir Raza

Thanks, its working now.

- Adrien Sleeg

Very interesting article !!
But the download link doesn't work for me...

- Mike

I've revised the link to point to this site. Previously, the download was being hosted on Sky Drive.

- yousaid

Great article !! Now how do you add a "Cancel" Functionality to the Edit mode. This is needed for those scenarios where the user changes their mind in the middle of the process.
Guess this is rather something very simple.

- Mike

You just need to add another button with the class "cancel", and then alter the edit-book click event to include items with a class of cancel:

$('.edit-book, cancel').on('click', function () {

- Emre

Hi this is really good work.Thanks for this.But i have a problem with sorting when i use this as u say.When i click headers to sort all hidden edit fields are opening.Do you have an idea for this why can i handle this problem?

- Om Prakash Bishnoi

Thanks, nice and very interesting article !!

- Marco

How would u handle validation?

- Mike


That's not an easy question to answer in a comment, and would very much depend on what is required.

- upen

this is really good, and how long are you in MVC ?

- Mike


I don't understand what you are asking. Sorry.

- Sithelo

Thanks a lot for an eye opener tutorial. In my application, I combined the inline and search functionality. Now when I click the edit button, it show the Save button for a spilt second.
In short the edit functionality s somehow hindered. How can I work around this?

- Patrick

Just what I needed! Thank you very much!!

- kkDubey

It's good...but where is stylesheet (edit-mode,display-mode,etc..)?

- Mike


The CSS classes you mentioned were not used for setting styles in the sample. They were simply used as selectors for jQuery. You can apply whatever style you like to them, though.

- Isaac Koss

Unfortunately this does not work in MVC 4. Do you have any ideas on how to do this in MVC 4? Thanks very much for your posts.

- Dragon

Nicely done, you edit and save, you dealt with cancel (indirectly) but what about delete? How do you delete a line item and then refresh (update) the grid?

- Dave

Great article. One small point though, you mention CRUD in several articles and in your book, but I haven't seen any of your code show how to implement the D(elete) portion. This article for example would be more complete if you showed how to delete an entry from the webgrid and then have the system refresh the display.

Just a thought, but great work and what is presented is very informative, so thanks.

- bluers0

How do you handle validations (e.g. you enter the same ISBN for 2 different books)?

- Alex

That's just what I was looking for thanks. How would I add fields that are a 1 or 0 in the database as a checkbox on the webgrid?

- Mike


You can pass an input type="checkbox" to the format parameter with the following attribute:

checked="@(item.value == 1)"

where 'value' is the database field that you want to bind to.

- Joop Stringer

How to add a row for a new record ?

- Mike


See this article: Adding a New Row In The Razor WebGrid

- faysal

Nice one can you please tell us how we can do ad and delete functionality in this. for e.g if i click on add row added and click on delete to delete row from grid.

Thanks in advance.

- Mike


You can find out how to add new rows in this article: Adding a New Row In The Razor WebGrid

- Wayne Hudson

Thank you very much for your articles. They've helped me a lot.

How would you handle inline editing such as a row where (in my case) number * amount = totalAmount?

Where totalAmount is a calculated field shown on change of either number or amount without saving?

- Mike


You should post a question to a forum and when you do, you should provide more detail about what it is you are trying to do.

- Jaswinder Singh


First of all, thanks a lot for writing a very nice articel about editing in webgrid.

It seems like this is not working in MVC5. I am getting the below message for the Dropdownlist

CS1501: No overload for method 'DropDownList' takes 5 arguments

Any idea?

Thanks again

- Mike


The article is written for the Web Pages framework, not MVC. It uses the Web Pages helpers which are different to the ones available in MVC. You should choose an MVC version that suits your needs:

Recent Comments

Cyrus 26/05/2017 06:00
In response to Razor Pages - The Elevator Pitch
There are some concern about razor pages performance. Is it faster or slower than MVC? would you a a...

Cyrus 26/05/2017 05:44
In response to Razor Pages - Understanding Handler Methods
well done, thank you....

Satyabrata Mohapatra 23/05/2017 11:41
In response to Razor Pages - Understanding Handler Methods
Nice and easy !! Great post....

Cyrus 16/05/2017 19:55
In response to Razor Pages - Getting Started With The Preview
There is something wrong related to microsoft.dotnetcore.mvc.taghelpers! if you remove it from page...

Cyrus 16/05/2017 10:18
In response to Razor Pages - Getting Started With The Preview
well done mike, it was very useful, I really appreciate that....

Satyabrata Mohapatra 16/05/2017 07:21
In response to Razor Pages - Getting Started With The Preview
Finally!!!! web pages in core!!! Super excited !!!! Thank u sir for sharing.....Awaiting on...

Daniele 14/03/2017 10:24
In response to Working With Zip Files In ASP.NET MVC
is it possible give to the user a progress bar of the zipping process? Thanks in advance. ...

Suraj 13/03/2017 22:20
In response to Working With Zip Files In ASP.NET MVC
Very nice article. Thanks....

Satyabrata Mohapatra 19/02/2017 03:01
In response to Free SSL Certificates On IIS With LetsEncrypt
Thanks for sharing. Learned a lot !!...

Gfw 03/02/2017 09:48
In response to Free SSL Certificates On IIS With LetsEncrypt
I have used WinSimple for about the last 9 months - works great. One thing that you want to make of...