Reusable Editable Fields for ASP.net MVC Using jQuery

Reusable Editable Fields for ASP.net MVC Using jQuery

10/08/2009 15:03:30

A friend recently asked me about editing items inline using ASP.net MVC, the kind of thing that was auto magically wired up with post backs in “old fashioned” asp.net so I’ve whipped up a small example showing how you can use jQuery to declaratively set up interactive field editing with a sprinkling of Ajax and JSON.

I’m basing this example on the default ASP.net MVC starter project for brevity (download attached) but here’s an overview:

First you need to set up an Action method (or multiple action methods) on your controller to accept the modification of data.  In my example I’ve added an unimaginative method called “SetField” to the HomeController that looks like this:

public ActionResult SetField(string fieldName, string fieldValue)
{
    var response = Json(fieldValue);
    return response;
}

As you can see, it doesn’t do very much (useful implementation left to the reader) but it accepts the parameters of a field name, and a field value.  You’ll need to roll your own validation and sanity checking here.  It then returns the fieldValue using the MVC Json helper object, as a Json object.  In a real world example, you’d want to call and update in this method.

Now, in the view, jQuery does most of the hard work.

First I added a few CSS classes to the header on the master page (for the sake of example):

<style type="text/css">
    .editableItem { display: block; }
    .fieldViewer { display: block; }
    .fieldEditor { display: none; }
    .editableItemCancel { display: block; }
    .editableItemBox { display: block; }
</style>

I then added an example to the view that looked like this:

<div class="editableItem" id="editable_FieldName">
    <div class="fieldViewer">Click me to edit me!</div>
    <div class="fieldEditor"><input class="editableItemBox" type="text"/><span class="editableItemCancel">cancel</span></div>
</div>

With this HTML I set up some conventions that I’ll rely on when using jQuery.  Firstly, every editable item should use the class “editableItem” and have the id “editable_FieldName”.  I use the class in a jQuery selector and the Id to establish which field is being edited.  Inside the editableItem should be a fieldViewer, containing the current data, and a fieldEditor, which is hidden by default, and contains some kind of editable controller and a cancel button.  You could insert these elements at runtime if you wished, but in order to keep the example simple I’ve declared them in the HTML.

Next I added some jQuery… The jQuery defines some Javascript behaviour associated with the classes used in the HTML, this way, the mark-up can be reused to edit multiple fields rather than being keyed to the Id of a specific field.

<script src="/Scripts/jquery-1.3.2.js" type="text/javascript"></script>
<script type="text/javascript">
    jQuery(document).ready(function() {

        $(".editableItem .fieldViewer").click(function() {
            var parentId = $(this).parent().attr("id");
            $('#' + parentId + " .fieldEditor .editableItemBox").val($('#' + parentId + " .fieldViewer").text());
            $('#' + parentId + " .fieldViewer").toggle();
            $('#' + parentId + " .fieldEditor").toggle();
        });

        $(".editableItem .fieldEditor .editableItemCancel").click(function() {
            var parentId = $(this).parent().parent().attr("id");
            $('#' + parentId + " .fieldViewer").toggle();
            $('#' + parentId + " .fieldEditor").toggle();
        });

        $('.editableItem .editableItemBox').keypress(function(e) {
            if (e.which == 13) {
                var parentId = $(this).parent().parent().attr("id");
                var fieldName = parentId.replace(/editable_/, "");

                $.post('/Home/SetField',
                {
                    fieldName: fieldName, fieldValue: $('#' + parentId + " .editableItemBox").val()
                },
                    function(data) {
                        $('#' + parentId + " .fieldViewer").text(eval('(' + data + ')'));
                        $('#' + parentId + " .fieldViewer").toggle();
                        $('#' + parentId + " .fieldEditor").toggle();
                    })
            }
        });

    });
</script>

Quite simply, if you click the editable field, it toggles into a textbox.  If you hit enter on the textbox, the value is posted to the previously defined Action on the Controller.  If you hit cancel, the display is toggled back.

I’d not recommend copy and pasting this exact example into a production system, but hopefully it’ll guide you through a simple scenario.  You can use a similar technique to add all sorts of little Ajax tricks (auto-suggest, lookups, dynamic menus) to your ASP.net MVC site using jQuery and Json (both of which are included in the core asp.net MVC framework).

Download the example solution here