Introduction

If you ask people what the most important thing that they want for web based application UIs, most of them will answer "I want to edit data really fast, like in Excel!" That is a tough request. It means that the person wants to click on a row, edit some data, then click on another row, and have all the data saved into a database. We've found a solution for this during TargetProcess v.2.6 development. TargetProcess is a great agile project management software (if you are not aware

Problem

The ASP.NET framework provides inline editing functionality in GridView. But sometimes, you get into situations when you cannot use this functionality:

You cannot use it with a disabled View State.

Performance is really bad. When you click a button to switch the row into edit state, a post back to the server will be initiated. The post back will happen when you save or cancel the edit mode as well. Even if you put your grid into an UpdatePanel, AJAX.NET still will update the whole grid instead of just one row, and the size of the date in the post back remains almost the same (and large).

With bad performance, it will not be like Excel, right? So, we have to look for a solution that:

Will not initiate post back to the server

Will work with a disabled view state

Will be as fast as Excel (at least, less than a second to do an action)

Solution

The Inline Edit Controller (IEC) is JavaScript solution that resolves all our problems (you will see it really soon). It has the following advantages:

It's a cross-platform solution, you can use it in any environment: ASP, ASP.NET, PHP, JSP etc.

It can be easily integrated into existing applications without almost any rework. You can define custom saving methods to put edited values into a database.

Basic principles

IEC is a plain JavaScript solution that allows editing rows in a grid. In order to have an editable row, you should mark the row in some specific manner. Let's call this stuff "Inline Edit Panel". It contains a button that enables inline editing as well as buttons that save changes and cancels editing. In fact, the better way to go is to enable editing on double click, and cancel it on Escape key. That will be shown in more advanced examples. So far, we have simple buttons:

As you can see, the "Inline Edit Panel" has three buttons, with an extra "action" attribute. Each action attribute fires the corresponding event. The IEC handles all these events and makes the corresponding changes in the DOM. Let's review the editing process now.

1. User clicks the Edit button

At this stage, the row switches to an editable state, and input and select boxes are appended to "Edit Areas".

The usual text labels become invisible. It means that the Freight label in the code above becomes invisible, and the input text field is added to the span with id="FreightIdPrefix777".

2. User changes some values and clicks the Save button

At this stage, IEC extracts all the values from editable fields (input, select, other if any).

Replace the label texts with new values from the editable fields.

Create a JavaScript object that holds the edited (new) values.

It's time to save changes into the database. IEC has no idea how to save new data, so it just passes the JavaScript object that holds the new values into the saving method.

3. User pushes the Cancel button

At this stage, IEC removes editable fields ("input", "select").

Labels become visible again.

Usage example

The idea looks really simple. But maybe, the solution is hard to use, who knows… Only a real example can help us judge the solution.

Let's take an ASP.NET example with:

A GridView control to present the data.

A Web Service to retrieve the data and save the modified data.

AJAX.NET to generate web methods that can be used from JavaScript.

For example, we have a pretty simple Order class. We want to show all the orders in a grid.

The GridView initialization is a no-brainer as well. OrderService is a class that can retrieve orders from the database (we don't care how; maybe the GetAllOrders method uses NHibernate, or maybe plain old SQL).

areaName – used by IEC to map the edited values to the retObj that is passed into onSaveEventHandler.

areaPrefix – used by IEC to find the edit area.

dataSourceControlID – data source control ID that has a collection of predefined values.

isFocused - boolean value that specifies whether the edit area will have a focus.

onRenderPriorityValue and onSelectPriorityValue are custom handlers that are implemented outside of IEC. It is impossible to implement all the cases of editing, and for specific situations, you have to create custom handlers. For example, the Priority column is an image. When the row is in the usual state, it shows the priority icon, but when the row is in an editable state, it should show the select box.

The code of onRenderPriorityValue and onSelectPriorityValue are out of the scope for this article; it will be described in Part II (architecture, extensibility, and stuff like that).

We are getting closer to the final. Let's add the saving handler. IEC is quite agnostic to data saving, and does not care how you will implement that. All it needs is a method call that does all the job.

The UpdateOrder method will be fired on the save event. It has only one input parameter, retObj, which holds all the edited values. IEC maps the edited values into retObj using the keys from EditAreaSettings (for example, shipName, Freight). Fortunately, I mapped the "Edit Areas" for IEC to be consistent with the Order class, except retObj.itemID that is created by IEC. As a result, retObj can be casted to the Order class. I had to do one extra assignment to make retObj completely consistent with Order.

retObj.OrderID = retObj.ItemID

The onSaveEventHandler handler is completely consistent with the web method.

Hello,
I have used this code to display data in the grid and it works great!
However, I have a requirement where one of the column is a derived comum; meaning the value is based on what the user enters in another column,
For example:
In the demo example, I would like to add a new column which is read only and this coum will be called FreightSurcharge which will be 10% of Freight. When the user enters a number in freight the FreightSurcharge should automatically be populated by using logic as
FreightSurcharge = Freight * 0.10
I was able to add that extra column but not sure how to do this auto populate.
Any help with the JavaScript would be greatly appreciated. I already spent several hours and was not successful.

The request failed with HTTP status 405: Method not allowed.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Maybe I am missing something here but I don't see where this is Ajax. Also there is no web config setting for your web service for data access. I had to figure out and add the following to my web service, web config.

Wow I was working on a project where I needed a grid that could be updated inline (inclusing adding new rows and deleting) and that addresses almost the same problems that you have addressed. I also needed a way to bring ADO.NET datatables to and from it and ability to then use ado table adaptor, so had to implement row sates. Going to study your grid and maybe improve some things in mine

I think that this is the sort of approach that needs to be taken to implement true inline editing - UpdatePanels suck at it, in terms of performance.

There are a couple of issues though that I wonder if you have come across yet, mainly to do with validation controls on inline fields. Most clients will usually want some sort of validation logic on editable fields, including appropriate error messages, and the usual approach would be to use the ASP.NET validation controls, which is possible using UpdatePanel / GridView as the validators can be executed on the server during partial page rendering.

Here I don't see an easy way to do the field validation as the actual edit fields are dynamically generated on the client, which would preclude me from using this solution - is this something you've handled yet?

Also there is the question of what form a field in edit mode takes - some fields might require a dropdown list or a date picker control instead of just being text boxes, so there should be some way to specify the field template as well. Again, ASP.NET has already solved this problem in the GridView et al.

There's a bit of a pattern here - to get the richest functionality, ASP.NET currently does it better, but with poor performance relative to other forms of AJAX. If you could come up with a solution that offers equivalent functionality but with better performance, then I think you'd have quite a nice bit of IP, especially if you could abstract the client code into a server control model that encapsulates the HTML and JavaScript required on the client.

You are right about validation, field forms and server control. This problem resolved and we will put the description into Part II of the article. In fact this framework allows to create custom handlers that will provide any possible edit field like drop down, date picker, checkbox and so on.

Completely agree with you.
We are going to submit Part II, there will be interested topics called "Extending the base functionality" and "Input Validation" as well as code update. Probably, it would be interested for you.

The text box is not only one form of field, the dropdown box with predefined values is also provided. It's pretty simple to bind "EditArea" with dropdown box, all what you need is to just specify id of select element that is supposed to be hidden in page.