In this article, I will show you a jQuery alternative for content editable - the Jeditable plug-in. I will also explain how you can implement inline editing functionality in an ASP.NET MVC3 application using jQuery.
Table of Contents
Introduction
You have probably seen a new HTML5 feature called contenteditable. It enables you to edit any element in HTML using the inline editor. The only thing you will need to do is attach some event handlers that will be called when editing is finished and send the new content to the server-side. If you like this HTML5 feature, you will love this plug-in.
Although the contenteditable feature is nice to have, if you have tried to use it in your web applications, you have probably noticed that you need to implement a lot of other functionalities such as sending AJAX requests to the server side, handling errors, validation, etc. Also, it works great if you edit plain text, however if you want to use some other editor such as calendar, check box, or select list where you don't want to enable the user to enter anything, you will see that regular contenteditable is not sufficient enough.
In this article, I will show you a jQuery alternative for content editable - the Jeditable plug-in. Also, here I will explain how you can implement inline editing functionality in an ASP.NET MVC3 application using jQuery. The Jeditable plug-in enables you to create an click and edit field as shown in the following figure:
On the left side is shown a simple HTML page, and on the right side is shown this page when you click on the text. The text will be replaced with a text area, and two buttons for save and cancel will be generated. When you finish with editing and click the OK button, text in the text area will be posted to the server page and new text will be placed instead of the old one. You can see this in the live examples on the Jeditable demo site.
The Jeditable plug-in can be easily customized (e.g., to use text input or select a list instead of a text area, change style/behavior, etc.) as explained in the rest of the article. On the demo page with custom examples see various examples with different editor types. Also, it will handle for you communication with the server side page.
Background
The Jeditable plugin is a very useful plugin that enables inline editing of HTML. With the Jeditable plugin, you can enable users of your application to simply click on the element they want to change and modify it immediately without a separate edit form.
The idea behind the Jeditable plugin is to replace static elements with the appropriate form element where the user can edit content and submit it to the server-side. As an example, let us assume that you have placed some static HTML element in the page - something like the following HTML code:
<span id="txtUser">John Doe</span>
This is a plain text field. You can enable the user to click on this field and edit it using the following JavaScript call:
$("#txtUser").editable("/ServerSide/Update");
Each time the user clicks on the element with the ID txtUser
, the Jeditable plugin will convert this element to a text box, put the content of the element in the text box value, and post a new value to the /ServerSide/Update URL via an AJAX call when the user presses Enter. If the value is successfully saved on the server-side page, the Jeditable plugin will replace the old value of the element with the new one.
The Jeditable plugin will handle all interactions on the user interface, and the only thing you will need to do is configure the plugin and implement server-side logic that handles the changed values.
Using the Code
In this article, I will explain how to use the Jeditable plugin in an ASP.NET MVC3 application. In the following sections are described details about the model, view, and controller that will be used in the example.
Model
In this example, a simple model representing a company is used. The source code for the model class is shown in the following listing:
public class Company
{
public int ID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Town { get; set; }
}
View
View is a standard Razor page where details about the company are displayed.
@model JQueryMVCEditable.Models.Company
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Details</h2>
<fieldset>
<legend>Company</legend>
<input type="hidden" id="CompanyId" value="@Model.ID" />
<div class="field">
<div class="display-label" id="lblName">Name</div>
<div class="display-field text" id="Name">@Model.Name</div>
</div>
<div class="field">
<div class="display-label" id="lblAddress">Address</div>
<div class="display-field textarea" id="Address">@Model.Address</div>
</div>
<div class="field">
<div class="display-label" id="lblTown">Town</div>
<div class="display-field select" id="Country">@Model.Town</div>
</div>
</fieldset>
Controller
The basic function of the controller is to get the company object (model) and provide it to the view. The code for showing details about the company is shown in the following listing:
public class CompanyController : Controller
{
public string Details(){ ... }
}
In order to show company details, you will need to enter the URL /Company/Details. There are two other methods in the controller that accept AJAX calls from the Jeditable plug-in (this will be described below).
Once you run this code, you will get the standard details page as shown on the following figure:
You might notice that this is a standard, unstyled MVC details page generated by Visual Studio. It contains a fieldset
with the label "Company
", where I have placed three company fields (company
, name
, address
and town
) with labels. In the next section, I will show you how you can convert this static view into fully editable elements.
Applying the Jeditable Plugin
In this section, I will show you how you can implement fully inline editable functionality in the details page.
Configure Editable Labels
In the first example, we will make the labels editable so the user can change them directly on the page. In the page, each input field has its own label such as:
<div class="display-label" id="lblName">Name</div>
In the page, I have placed a display-label
class in each div
that represents a label. I will use this class to make the label editable. jQuery code that applies the Jeditable plugin on the labels is shown in the following listing:
$(".display-label").editable("/Company/UpdateLabel");
Each time you click on the label, it will be converted to text input where the user can enter a new value for the label. This is shown in the following figure:
As you can see, clicking on the label "Name
", it is converted into text input.
When the user presses the Enter key, a value of the new label will be sent to the /Company/UpdateLabel server side page. In the request will be sent two values:
id
- ID of the label. This value can be used on the server side to determine what label should be updated. value
- text that is entered in the input field.
An example of such a kind of request is shown in the following figure:
On the server side should be added a controller with the action method that will be called when the /Company/UpdateLabel request is sent. An example of the controller and action method is shown in the following listing:
public class CompanyController : Controller
{
public string UpdateLabel(string id, string value)
{
return value;
}
}
This action method accepts the ID of the label and a new value. Specific code for updating the label value in the database or configuration files is omitted because it is application specific and not directly related to the plug-in.
Configure Editable Fields
We can also make the field values editable. Let us assume that we have placed the ID of the current company in the hidden field with the ID CompanyId
, and that each field value is placed in the div
with class display-field
. Part of the HTML is shown in the following code:
<input type="hidden" id="CompanyId" value="@Model.ID" />
...
<div class="display-field text" id="Name">@Model.Name</div>
...
<div class="display-field text" id="Address">@Model.Address</div>
...
<div class="display-field text" id="Town">@Model.Town</div>
We will assume that each field that should be editable has a class "display-field
". jQuery code that applies the Jeditable plugin on the editable fields is shown in the following listing:
$(".display-field").editable("/Company/UpdateField",
{
submitdata : {
CompanyId: function() {
return $("#CompanyId").val();
},
RecordType: "COMPANY"
}
});
Each time you click on the element with the class editable
, it will be converted to text input as shown in the following figure:
When the user presses Enter, a new value of the element will be sent to the server side page /Company/UpdateField. In the request, four values will be sent:
id
- ID of the field. This value can be used on the server side to determine what property of the company should be updated. value
- Text that is entered in the input field. CompanyId
- This is an additional parameter that will be added to the request. The value of this parameter is a value of the hidden field with an ID "CompanyId
". RecordType
- This is an additional parameter that tells the server that we are editing company.
As you can see, the code is very similar to the previous code, with a difference in the two additional parameters, CompanyId
and RecordType
. As we are editing particular companies and not global labels, we should have on the server side the ID of the company where we are changing the field value. I have placed the ID of the company in the hidden field with ID 'CompanyId
' and the Jeditable plug-in takes this value and adds it to the request parameters when requests are submitted.
Also, sometimes we would need to know on the server side if we are editing companies, jobs, people, products, etc. Therefore, it would be nice to have some additional parameters that send information about what the type of the record is that we are editing. In this example, this is achieved using the second custom submitdata
parameter called RecordType
. The server-side page will check the value of this parameter and update either company, job, product, etc. In this simplest example, we have only companies so this parameter is not used. As an alternative, you can use different URLs for different record types (e.g., '/Company/UpdateField', 'Product/UpdateField', 'Job/UpdateField', etc.) if you do not want to have an additional parameter. A trace of the AJAX call that is sent to the server-side is shown in the following figure:
On the server side, a controller with the action method that will be called when the /Company/UpdateField request is sent should be added. An example of the controller and action method is shown in the following listing:
public class CompanyController : Controller
{
public string UpdateField(string id, string value, int CompanyId, string RecordType)
{
return value;
}
}
This action method accepts the ID of the field, the new value, the ID of the company, and the type of the record we are editing. Specific code for updating the company field value in the database is omitted because it is application specific and not directly related to the plugin.
Configuration of the Jeditable Plugin
The default functionality can be easily changed by setting different options in the plugin initialization call. Options are set as a second parameter in the Jeditable call. In this section, different options that can be applied will be shown.
Customize Submit Options
By default, clicking on the element will initiate the Jeditable plugin and pressing the Enter key will be considered as accepting changes. Losing focus from the element (blur) or pressing the ESC key will be considered as cancel action. You can change these options and add separate buttons for the accepting and canceling actions, which will be injected beside the text input. In order to configure the submit
and cancel
buttons, you will need to set these parameters in the initialization:
$(".editable-field").editable("/Company/UpdateField",
{
cancel : 'Cancel',
submit : 'OK'
});
If cancel and submit parameters are not set, the buttons will not be generated.
Changing the Editor Type
The text box is a default editor, however you can use a text area of a select list as an alternative editor. In order to use a text area instead of text input, you should just change the value of the parameter type
as shown in the following example:
$(".textarea").editable("/Company/UpdateField",
{
type : 'textarea',
rows : 4,
columns : 10,
cancel : 'Cancel',
submit : 'OK',
});
Note that when you use the text area input, you should add a Submit button because in the textarea, an Enter key adds a new line so it cannot be used for submitting a value. Look of the editor configured as a text area is shown in the following figure:
Another editor type is a select
list where you can define a set of options that might be selected. An example is shown in the following listing:
$(".select").editable("/Company/UpdateField",
{
type : 'select',
data : "{'Belgrade':'Belgrade','Paris':'Paris',
'London':'London', 'selected':'Belgrade'}"
});
In this example, the select
list containing three values is generated. Note that the last parameter tells the Jeditable plugin which value should be selected. Instead of the hardcoded values in the data
parameter, you can load options from the server-side URL:
$(".remote-select").editable("/Company/UpdateField",
{
type : 'select',
loadurl : '/Company/Options',
loadtype : 'GET',
loaddata : {type: "1"};
});
When the user clicks on the element, a /Company/Options?type=1 request will be sent to server-side using the GET
protocol. The returned values will be used as options in the select list. A select list editor is shown in the following figure:
Text box, text area, and select list are standard editors, but there are other custom types such as checkbox
, datepicker
, file upload, time editor, etc. Some of them are shown on the Jeditable demo page.
If you cannot find an editor type you need, you can create your own editor - see this tutorial for more details.
Configure Submitted Data
By default, the Jeditable plug-in sends the ID of the element and value that is entered in the input element to the server-side URL. However, you can customize these settings as shown in the following example:
$("#txtTitle").editable("/Company/UpdateField",
{
id : 'COMPANY_FIELD',
name : 'FIELD_VALUE',
method: 'POST',
submitdata : {type: "company"}
});
Additional options are:
id
: Name of the submitted parameter which contains the content ID. Default is id
. name
: Name of the submitted parameter which contains edited content. Default is value
. method
: Method to use when submitting edited content. Default is POST
. You most likely want to use POST
or PUT
. submitdata
: Extra parameters when submitting content. Can be either a hash or function returning a hash. You saw how this function is used in the example above in order to add a company ID parameter from the hidden field.
When Jeditable submits a request to the server-side, the POST
request will look like: /Company/UpdateField?COMPANY_FIELD=Name&FIELD_VALUE=TEST&type=company.
As you can see, the id
and value
parameters have different names, value is encoded, and a new parameter called type
is added to the request.
Configure Display/Behavior
The way the editable plugin is activated can be set in the configuration. This is configured using the event
and onblur
parameters:
$("#txtTitle").editable("/Company/UpdateField",
{
event : 'click',
onblur : 'submit'
});
The parameter event
is a jQuery event that will convert the content to editable input (e.g., 'click
' , 'dblclick
, or 'mouseover
'). The onblur
parameter can have one of these values: 'cancel
', 'submit
', 'ignore
', or can be set to a function. This parameter will define what the plugin does when input loses focus.
You can change the way Jeditable is displayed. You can set the style or associate a CSS class with the form where the inline editor is placed. If you put the value 'inherit
', a class or style from the surrounding element will be placed in the form. Also, you can define the width and height of the editor. An example is shown in the following listing:
$("#txtTitle").editable("/Company/UpdateField",
{
cssclass : 'inherit',
style : 'display:inline',
height : '20px',
width : '100px'
});
In this configuration, a CSS class will be inherited from the surrounding element, the form will be displayed inline, and dimensions of the textbox will be 20x100px.
You can also define what text will be shown if a current one does not exist, what will be used as tooltip text, and what text/HTML will be shown while the server is saving the edited value:
$("#txtTitle").editable("/Company/UpdateField",
{
placeholder : 'N/A',
tooltip : 'Click to edit',
indicator : 'Saving...',
select : true
data: function(value, settings) {
return encode(value);
},
});
In this example, if the element does not have any content 'N/A
' will be displayed (default value is 'Click to edit
'), tooltip will be 'Click to edit'. While the plugin waits the answer from the server, text 'Saving...
' will be displayed. You can put HTML instead of the plain text if you want. Once user edit the text, it will be automatically highlighted because select property is set to true.
Data
parameter represents the data that will be shown in the editor. In the previous example with the select editor type, in the data element was placed list of options that will be placed in the select list. If you put a function as a data parameter, it will be called before Jeditable takes the current text from the element, this text will be passed to the function, and the returned value will be set as the content of the editor element. It can be either a string or function returning a string
. This can be useful when you need to alter the text before editing (e.g., encode it as shown in the example).
Event Handling
Many events can be handled in the Jeditable plug-in:
callback
- function(value, settings) { ... } is called after the form has been submitted. value
contains the submitted form content. settings
contain all the plug-in settings. Inside the function, this
refers to the original element. onsubmit
- function(settings, original) { ... } called before submit. settings
contain all the plug-in settings. original
is the original content of the element. Inside the function this
refers to the original element. onreset
- function(settings, original) { ... } called before reset. settings
contain all plug-in settings. original
is the original content of the element. Inside the function, this
refers to the original element. onerror
- function(settings, original, xhr) { ... } called on error. settings
contain all plug-in settings. original
is the original content of the element. Inside the function, this
refers to the original element.
Integration with Other Plug-Ins
The beauty of the Jeditable plugin is the fact that it can be applied on top of any other plugin. As an example, you can apply inline cell editing in table cells, edit nodes in the tree view or in the menu, edit content of tabs, etc. The only thing you need to do is apply the Jeditable plugin on the elements that should be edited. In the following examples, you might find two usages of editable plugin with tabs and tables.
Integration with JQuery UI Tabs
JQuery UI tabs is a part of JQuery UI library and it enables you to easily create tabbed interface. You can find a various cases of usage on the JQuery UI Tabs page. Example of tabbed interface is shown in the following figure:
Each tab in the picture is a link in the format <a href="#tab-1">Nunc tincidunt</a>
, <a href="#tab-2">Proin dolor</a>
, <a href="#tab-3">Aenean lacinia</a>
, where tab-1
, tab-2
, and tab-3
are ids of tab contents. You can apply editable plugin on the tab links using the following code:
$("#tabs").tabs();
$("a[href='#tabs-1']").editable("/Settings/UpdateTabLabel",
{ event: "dblclick",
submitdata: { id: "tab-1" }
});
Editable plugin is applied on the link that point to the first tab (via href attribute). When user double-click on the tab link and edit tab label, JEditable plugin will post new value to the page /Settings/UpdateTabLabel
with the changed value and id "tab-1
". On the following figure is shown how you can edit the first tab:
Similar script can be applied to make the other tabs editable.
Integration with DataTables
JQuery DataTabes plugin adds pagination, filtering and sorting in the table. Once you apply DataTables plugin, you can apply editable plugin on the cells. In the following figure, you can see how the Jeditable plugin can be applied on the table cells:
In this example, the jQuery DataTables plug-in on the table is applied, and then JEditable is applied to particular cells. Script that applies editable plugin on the table cells is simple:
$("table#mycompanies td").editable("/Company/UpdateTableCell");
As long as each cell has its own id JEditable plugin will work. Better solution would be to avoid ids in each cell and send just id of the row and column with value. In that case, you might take a look at the already prepared solution for applyng editable plugin on the DataTable
on the DataTables site or DataTable Editable plugin that combines features of DataTables and JEditable plugins. You can see more details about creating an inline editable cell in the ASP.NET MVC Editable Table[^] article.
Conclusion
In this article, basic concepts of implementation of an inline editor in MVC3 are shown. I have also shown various configuration options. If you have any questions about the Jeditable plug-in or you need more info about the way it is used, please take a look at the Jeditable site where you will find a complete documentation with live examples.
Attached is the source code with the Web Developer 2010 project where a simple page containing editors is implemented.
History
- 17th October, 2011: Initial version