WebMatrix and jQuery Forms Part 2 - Editing Data

This article continues on from one I wrote a while ago, showing how to use jQuery to create a data entry form in conjunction with the WebGrid. The original article prompted a number of requests to show how to extend the example to provide editing functions, and now I have found some time to answer those requests.

The initial article uses a sample database I created which contains details of books and their authors. The example code in that article is quite straightforward. Once you have worked out how to use the jQuery Dialog, you use that to display a data entry form, and when the new book is added, you give the first row of the grid a highlight effect. The task of adding Edit features poses are few new challenges. For one thing, the dialog form must know which book's details it should display so that the user can alter them. Secondly, the items location in the grid (row and page) must be known so that the correct row can be highlighted.

The edit form works in the same way as the Add form, in that it is defined in the Default.cshtml file and the jQuery dialog command is what gives it life:

    <div id="dialog-form-edit" title="Edit Book">
    <form id="edit-book-form" action="@Href("~/Methods/UpdateBook")">
         <div class="row">
                <span class="label"><label for="title">Title:</label></span>
                <input type="text" name="title" id="edit-title" size="50" />
            <div class="row">
                <span class="label"><label for="isbn">ISBN:</label></span>
                <input type="text" name="isbn" id="edit-isbn" size="20" />
            <div class="row">
                <span class="label"><label for="description">Description:</label></span>
                <textarea cols="50" rows="8" name="description" id="edit-description"></textarea>
            <div class="row">
                <span class="label"><label for="authorId">Author:</label></span>
                <select name="authorId" id="edit-authorId">
                    <option value="">-- Select Author --</option>
                    foreach(var author in authors){
                        if(author.AuthorId == Request["authorId"].AsInt()){
                            <option value="@author.AuthorId" selected="selected">@author.AuthorName</option>
                        } else {
                            <option value="@author.AuthorId">@author.AuthorName</option>
            <div class="row">
                <span class="label"><label for="categoryId">Category:</label></span>
                <select name="categoryId" id="edit-categoryId">
                    <option value="">-- Select Category --</option>
                    foreach(var category in categories){
                        if(category.CategoryId == Request["categoryId"].AsInt()){
                            <option value="@category.CategoryId" selected="selected">@category.Category</option>
                        } else {
                            <option value="@category.CategoryId">@category.Category</option>
            <div class="row">
                <span class="label"><label for="datePublished">Date Published:</label></span>
                <input type="text" id="edit-datePublished" name="datePublished" />
                <input type="hidden" id="edit-bookId" name="bookId" />

The form is pretty much identical to the Add Book form, except that the action has changed, and the id values for the form elements have been prefixed with "edit-". With a bit more effort, you could probably find a way to reuse the same form instead of creating a separate form for each operation. In the meantime, you need something to instantiate this form in a dialog, and it needs to know which book it should populate itself with so that you can amend the details. That is the job of the following piece of jQuery:

$('.edit-book').live('click', function(){
    $.getJSON('/Methods/GetBook/' + $(this).attr('id'), function(data){
        var book = data;
        var date = new Date(parseInt(book.DatePublished.substr(6)));
        var year = date.getFullYear();
        var month = date.getMonth() + 1;
        var day = date.getDate();
        $('#edit-datePublished').val(year + '-' + month + '-' + day);
        $('#edit-datePublished').datepicker({ dateFormat: 'yy-mm-dd' });

This block of code looks for items with a class of edit-book, and attaches a click event handler to them. Those items are buttons in the first column of a revised WebGrid:

@grid.GetHtml(tableStyle: "ui-widget ui-widget-content",
              headerStyle : "ui-widget-header",
              columns : grid.Columns(
                grid.Column("", format: @<button class="edit-book" id="@item.BookId">Edit</button>),
                grid.Column("AuthorName",header : "Author"),

The buttons have the Id of the current book applied as their id attribute value. The preceding block of jquery uses live to bind the event handler. This ensures that all existing items - and all items that are created in the future - with the specified class have the event handler bound to them. This is important when you have AJAX paging enabled. When a button is clicked, the Id of the current book is passed to an AJAX call to GetBook.cshtml in the Methods folder. The content of that file is as follows:

        var db = Database.Open("Books");
        var sql = "SELECT * FROM Books WHERE BookId = @0";
        var book = db.QuerySingle(sql,UrlData[0]);
        Json.Write(book, Response.Output);

This code simply queries the database for details of the book which is to be edited, and whose Id was passed in the URL. The top line of code prevents the browser (especially IE) from caching the result, which is output using the JSON helper. Once the JSON has been received by the calling block of jQuery, it is used to populate the edit form, and finally the dialog command is used to invoke the form in a dialog box. The code that controls the edit form once it has been created is as follows:

    autoOpen: false,
    modal: true,
    height: 425,
    width: 475,
    buttons: {
        'Edit Book' : function(){
                type: "POST",
                url: $("#edit-book-form").attr('action'),
                data: $("#edit-book-form").serialize(),
                dataType: "text/plain",
                success: function(response) {
                    $("#grid").load('/Default/?page=' + page + ' #grid', function(){
                    var id = $('#edit-bookId').val();
                        $('#' + id).parent('td').parent('tr')
                        .effect("highlight", {}, 2000);
                error: function(response) {
        Cancel: function() {
    }// end buttons

This is much the same as the add form in the previous article. The data in the form is sent to Methods/UpdateBook, which takes care of ensuring changes are committed to the database:

        var db = Database.Open("Books");
        var sql = @"UPDATE Books SET Title = @0, ISBN = @1, Description = @2, AuthorId = @3, 
                    CategoryId = @4, DatePublished = @5 WHERE BookId = @6";
        var title = Request["title"];
        var isbn = Request["isbn"];
        var description = Request["description"];
        var authorId = Request["authorId"];
        var categoryId = Request["categoryId"];
        var datePublished = Request["datePublished"];
        var bookId = Request["bookid"];
        db.Execute(sql, title, isbn, description, authorId, categoryId, datePublished, bookId);

If that operation was successful, the code makes an AJAX request for Default.cshtml (the page that the code is actually in) and passes a querystring value for the WebGrid page it wants to display. This value was obtained from the paging link via jQuery if one was used, otherwise it is assumed that the grid is still on page 1:

var page = 1;
$('tfoot a').live('click', function () {
    page = $(this).text();

Once the revised grid, complete with updated book details appears, the row containing the Id of the book that was updated is located, and the highlight effect is applied to the whole row.

The code is available as a sample site at GitHub


Date Posted: Saturday, August 6, 2011 5:33 PM
Last Updated: Tuesday, November 11, 2014 8:04 AM
Posted by: Mikesdotnetting
Total Views to date: 19629


Wednesday, July 17, 2013 4:02 PM - Craig

This is a great article! Exactly what I needed. Could you please also describe how to add validation, with both the unobtrusive client validation library, as well as the Razor Validation helpers? I have not been able to get the @Html.ValidationMessage Razor helpers to work on app of mine that uses the techniques described here.

Friday, December 6, 2013 8:52 PM - Alan

Great article, I followed most everything but the following line
$('#' + id).parent('td').parent('tr'). What does this do? I do not understand $('#' + id) say I have an id of 142 this will give a selector of value #142. I do not have this in the program.

Saturday, December 7, 2013 8:32 PM - Mike


It gets the id of the current item. If you followed the code properly, the only way you will get an id of 142 is if you have an item with that value as its id.
Add your comment

If you have any comments to make about this article, please use this form to do so. Make sure that your comment relates specifically to the article above. More general comments can be posted through the form on the Contact page.

Please note, all comments are moderated, and some may not be published. The kind of things that will ensure your comment is deleted without ever seeing the light of day are as follows:

  • Not relevant to the article
  • Gratuitous links to your own site or product
  • Anything abusive or libellous
  • Spam
  • Anything in a language I don't understand including gibberish.

I do not pass email addresses on to spammers, so a valid one will assist me in responding to you personally if required.

Recent Comments

stephen 1/28/2015 9:53 PM
In response to ASP.NET MVC 5 with EF 6 - Working With Files
Hi, Sorry for wasting your time, I had a comment <!--Images--> inside the form this stopped it from...

stephen 1/28/2015 9:47 PM
In response to ASP.NET MVC 5 with EF 6 - Working With Files
Everything has been ok up until this part, here's a snippet of the entire file but i removed lines =...

Stephen kenny 1/28/2015 8:26 PM
In response to ASP.NET MVC 5 with EF 6 - Working With Files
Hi, great article. My issue is with the create view. @using (Html.BeginForm("Create", "Reptiles",...

Jenelyn 1/27/2015 6:44 PM
In response to MVC 5 with EF 6 in Visual Basic - Implementing Basic CRUD Functionality
I'm searching CRUD using VB.net 2010 and I can't find any, how sad...

Kadu Portugal 1/23/2015 10:55 AM
In response to Scheduled Tasks In ASP.NET With Quartz.Net
Hi Mike, Thank you for your useful article. I implement it in my project, and everything run...

Satyabrata 1/23/2015 6:02 AM
In response to Usage of the @ (at) sign in ASP.NET
Refreshed a lot of things.Thanks...

Vo Thanh Chinh Trung 1/22/2015 4:30 PM
In response to Adding A View
It's very helpful...Thank you so much, Mikes!...

Joop Stringer 1/22/2015 12:00 PM
In response to Inline Editing With The WebGrid
How to add a row for a new record ?...

Gaetan C 1/21/2015 8:49 PM
In response to Looking At The WebMatrix WebGrid
I use the webgrid very often and I Wonder if it's possible to merge to different sql query into on...

Teresa 1/19/2015 3:08 PM
In response to MVC 5 with EF 6 in Visual Basic - Creating an Entity Framework Data Model
At the top, the first thing you write is "Open Visual Studio and create a new C# Web project named I...