Using jQuery to Handle Checkboxes in ASP.NET MVC 3

Let’s say we have a simple to-do list application in ASP.NET MVC which displays a table of open tasks. And below that table, we display a list of completed tasks.

Task List

The scenario is pretty straight forward – when a user clicks on an open task check box (to mark it complete) we need to update the database record for that task and then move it to the completed tasks list below. And vice versa – if a user changes their mind and unchecks the completed task, then we need to update the database record again and move that task back up to the open task table. There’s no submit button or form here – it’s going to be something we’ll handle dynamically with one click of a checkbox.

Here’s part of the HTML generated by our Razor view. Each task has a unique ID e.g. ‘checkbox1′ based on the task ID in the database i.e. 1. I just added the ‘checkbox’ prefix to avoid confusion with lots of ‘vague’ numbered IDs all over the place in the HTML.

<input id="checkbox1" name="checkbox1" type="checkbox" value="true" />
<input name="checkbox1" type="hidden" value="false" /> <a href="/item/Edit/1">Buy milk</a>
<input id="checkbox2" name="checkbox2" type="checkbox" value="true" />
<input name="checkbox2" type="hidden" value="false" /> <a href="/item/Edit/2">Write status report</a>
<input id="checkbox3" name="checkbox3" type="checkbox" value="true" />
<input name="checkbox3" type="hidden" value="false" /> <a href="/item/Edit/3">Pickup dry cleaning</a>

<li class="completed">
<input id="checkbox4" checked="checked" name="checkbox4" type="checkbox" value="true" />
<input name="checkbox4" type="hidden" value="false" />Schedule meeting with Bob<a href="/item/Delete/4">Delete</a></li>

First, we need to get our jQuery code working to handle the check and uncheck events for any of these tasks. All we’re doing here is getting the ID of the task that’s being checked (stripping out the ‘checkbox’ prefix), determining if a checkbox was checked or unchecked and then then passing that ID to the relevant action method in the Item controller i.e. “Complete” or “Incomplete” action method:

$('input[type=checkbox]').click(function () {
var itemid = this.id.substring(8);
if ($(this).is(':checked')) {
$(window.location).attr("href", "/item/complete/" + itemid);
} else {
$(window.location).attr("href", "/item/incomplete/" + itemid);
}
})

The “Complete” action method finds the record in the database using the ID that was passed to it from the jQuery function, updates the “Completed” column to “Y”, saves the database changes and then redirects to the “Index” action method (which displays the Razor view shown above).

public ActionResult Complete(int id)
{
Item item = db.Items.Find(id);

if ((item == null)
{
return View("NotFound");
}

item.Completed = "Y";
db.SaveChanges();
return RedirectToAction("Index");
}

The “Incomplete” action method basically does the same thing as the “Complete” action method above, but changes the “Completed” column value to “N” i.e. marks the task as open again.

I’m not sure if doing a redirect from the jQuery function to the relevant action method is the best way to handle this (versus a Post), but it seems to work okay. The next step will be to use some Ajax to just update the table & list without reloading the entire page, but I’ll leave that for another day.

Using jQuery with ASP.NET MVC 3

Using jQuery with ASP.NET MVC3 is pretty simple, especially now that it comes pre-installed with VS 2010. However, to set it up in a more scalable way with your project takes a little bit of work upfront but is definitely worth the extra effort in the long run.

1. Create a New Razor Helper
Let’s start by creating a new Razor helper in the App_Code folder (you may need to create this folder if it doesn’t already exist in your project). Add a new Razor view called Content.cshtml and replace the entire contents of that file with the following helper code:

@using System.Web.Mvc;

@helper Script(string scriptName, UrlHelper url) {
    <script src="@url.Content(" type="text/javascript"></script>
}

2. Add Script References to Layout Master
Add the following code to the end of _layout.cshtml (before the closing body tag).

@Content.Script("jquery-1.5.1.min.js", Url)
@Content.Script("jquery.unobtrusive-ajax.min.js", Url)
@RenderSection("scripts", false)

3. Adding New Script References
Adding any new script references is now easy. We can just add them to _layout.cshtml. Just be sure to add those references before the RenderSection line to ensure that the scripts load in the correct order.

@Content.Script("jquery-1.5.1.min.js", Url)
@Content.Script("jquery.unobtrusive-ajax.min.js", Url)
@Content.Script("jquery-ui-1.8.11.min.js", Url)
@Content.Script("modernizr-1.7.min.js", Url)
@RenderSection("scripts", false)

4. Adding Script References For Specific Pages
The RenderSection helper is used to call any page specific script references in the correct order i.e. after the main jQuery files have been loaded. The page specific script references can now be called in the same way i.e. simply add the required references to the relevant Razor view:

@section scripts {
    @Content.Script("jquery.validate.min.js", Url)
    @Content.Script("jquery.validate.unobtrusive.min.js", Url)
}

Voila! Now we’re ready to start having some fun with jQuery.