Sunday, April 3, 2011

Reorder Table Control Rows with "Drag and Drop"


Suppose you need to design a page for users to order a list of items, for example, assigning priorities to a list of tasks, or ordering questions in a questionnaire. ISD's out-of-box solution is an edit table control, in which a textbox is for entering each item's order. An obvious drawback of the solution is that users have to manually maintain the integrity of all orders, and  a change in one row may result in changes in other rows.

A slightly better design is to replace the textbox with a pair of up and down arrows. You can use custom code in the arrows' event handlers to switch order between the clicked item and its previous or next one. When the page is regenerated, the items are sorted on their new orders. This design guarantees order integrity, but is inefficient. In order to move an item from bottom to top of the list, it requires quite some clicks.

Wouldn't it be nice that user simply drag and drop an item to its desired position and its new order, as well as other affected items', is reassigned automatically? This post will show you how to implement it in ISD.


There are two candidate implementations for drag-n-drop ordering, AjaxToolkit's ReorderList and a jQuery plugin Table Drag and Drop (TableDnD). ReorderList is a data-bound server control. It asks for a list of items as data source, and takes full control of data-binding and rendering. ISD has little help to offer. On the other hand, TableDnD is a pure client-side solution, leaving ISD with full control at server-side. Therefore, I will use TableDnD in this implementation.


Step 1: Create a regular EditTable page
Create a plain vanilla EditTable page as shown below. Nothing fancy.

Step 2: Add jQuery and TableDnD libraries
In the page's prologue, insert 2 script references (lines 1 and 2):
Step 3: Configure HTML  table for DnD
Since ISD-generated pages are heavily loaded with HTML tables, it could be a little bit tricky to find the right one to configure. It is the inner most Fields table, as shown below.

First, give the table an unique ID. TableDnD will use the ID to locate the table and attach DnD behavior.

Then, add 2 classes (nodrag and nodrop) to the header row. This notifies TableDnD not to attach DnD behavior to the header row.

Step 4: Add CssClass to order field
Add CssClass (orderbox) to the textbox that holds the order field.

Step 5: Customize background color for the row in DnD
Add the following css class in Styles.css:
tr.tDnD_whileDrag td
  background-color: #CCCCCC;
Step 6: Attach DnD behavior
Finally, insert the following script into the page's epilogue:


It seems a lot of steps. But your users' uh-ah reaction makes it all worth the trouble. You can download the demo here.