Utilize HTML5 ContentEditable in ASP.NET MVC to Edit View Content
Usually ASP.NET MVC developers create two separate views for displaying data
in read-only and editable form. Although this technique works well, you can
utilize a feature of HTML5 to conveniently read as well as edit data on the same
view. HTML5 offers contenteditable attribute that magically turns any read-only
area of a web page into an editable region. Using contenteditable in combination
with some jQuery code you can easily develop a view that toggles between
read-only and editable mode.
Let's see how this can be accomplished with a simple example. Have a look at
the following view:

As shown above , the Index view displays Employee details such as EmployeeID,
FirstName, LastName and Notes. Notice that the Notes region, although appears to
be editable, is not a textbox! It's actually a <div> element whose
contenteditable attribute is set to true. The FirstName and LastName values are
also wrapped in a <div> that is contenteditable. A <div> element marked with
contenteditable enters edit mode when you click on it and becomes read-only when
you click somewhere outside on the page.
The following screen shot shows the Notes <div> after edit operation is over:

Although HTML5 contenteditable attribute allows you easily toggle between
read-only and edit mode, it doesn't automatically persist the changes to the
storage. But a dash of jQuery code can do that for you. Let's see how.
The following code shows the Index() action method of Home controller:
public ActionResult Index()
{
using (NorthwindEntities db = new NorthwindEntities())
{
return View(db.Employees.First());
}
}
The Index() action simply picks the first Employee record from the Employees
table of Northwind database and sends it to the Index view. For the sake of
testing the above code simply sends the first Employee object to the view.
The Home controller also has an action method - Save() - that does the job of
saving an Employee to the database. The Save() method is called through jQuery
code and is shown below:
public JsonResult Save(Employee obj)
{
using (NorthwindEntities db = new NorthwindEntities())
{
Employee existing = db.Employees.Find(obj.EmployeeID);
existing.FirstName = obj.FirstName;
existing.LastName = obj.LastName;
existing.Notes = obj.Notes;
db.SaveChanges();
return Json("Employee modified successfully!");
}
}
The Save() action receives an Employee object to be saved in the database and
returns a success message as a JsonResult. Inside, the code simply finds an
existing Employee, modifies the concerned properties and calls SaveChanges() to
save the data. You need to update the Employee this way because the Employee
object received in the Save() method doesn't have all the properties of the
Employee model class.
Next, you need to create the Index view and add the following markup to it:
@model ContentEditableDemo.Models.Employee
<!DOCTYPE html>
<html>
...
<body>
<h1>Employee Details</h1>
<table border="1" cellpadding="10">
<tr>
<td>Employee ID :</td>
<td><div id="employeeID">@Model.EmployeeID</div></td>
</tr>
<tr>
<td nowrap>First Name :</td>
<td>
<div id="firstName" contenteditable="true">
@Model.FirstName
</div>
</td>
</tr>
<tr>
<td>Last Name :</td>
<td>
<div id="lastName" contenteditable="true">
@Model.LastName
</div>
</td>
</tr>
<tr>
<td>Notes :</td>
<td>
<div id="notes" contenteditable="true">
@Model.Notes
</div>
</td>
</tr>
<tr>
<td colspan="2">
<input id="save" type="button" value="Save" />
</td>
</tr>
</table>
<br />
<span id="msg"></span>
</body>
</html>
Notice all the <div> elements marked in bold letters. They have
contenteditable attribute set to true. Thus FirstName, LastName and Notes
regions can be edited by clicking on the respective <div>. Clicking on the Save
button triggers some jQuery code that sends the modified Employee to the Save()
action wrote earlier. This jQuery code is shown below:
$(document).ready(function () {
$("#save").prop("disabled", true);
$("div").on('input', function () {
$("#save").prop("disabled", false);
});
$("#save").click(function () {
var modifiedEmployee = {};
modifiedEmployee.EmployeeID = $("#employeeID").text();
modifiedEmployee.FirstName = $("#firstName").text();
modifiedEmployee.LastName = $("#lastName").text();
modifiedEmployee.Notes = $("#notes").text();
$.post("/home/save", modifiedEmployee, function (msg) {
$("#save").prop("disabled", true);
$("#msg").html("<strong>" + msg + "</strong>");
});
});
});
When the page loads in the browser, you set the disabled DOM property of the
Save button to true. Since the Employee record is not yet edited the Save button
is disabled. The code then wires event handler for the input event of all the
<div> elements. This way you can trap when the content is modified (of course,
this is not a sophisticated and precise arrangement but tha's ok for our
example). In the input event handler you simple enable the Save button by
settings its disabled DOM property to false.
Then the code wires the click event handler of the Save button. The code
inside the click event handler forms a JavaScript object to store the Employee
details. It does so by grabbing the content of all the four <div> elements. It
then post this Employee object to the Save() action using jQuery $.post()
method. Once the Save() action returns successfully, the Save button is again
disabled and the success message returned from the server is shown in a <span>
element.
That's it! You can now run the application and test whether editing works as
expected.