Click here to Skip to main content
Click here to Skip to main content

Table Row Drag and Drop in ASP.NET MVC (jQuery DataTables and ASP.NET MVC Integration - Part VI)

, 23 Apr 2012
Rate this:
Please Sign up or sign in to vote.
Reordering table rows using drag and drop functionality with jQuery DataTables plug-in in ASP.NET MVC applications.

Table of Contents

Introduction

In this article I will explain how you can implement drag and drop reordering of rows in web tables. For drag and drop functionality we will use the jQuery UI Sortable plug-in combined with jQuery DataTables. A prerequisite is that the table is enhanced with the jQuery DataTables plug-in. An example of a table enhanced with the jQuery DataTables plug-in where drag and drop reordering is implemented is shown in the following figure:

The jQuery DataTables plug-in enhances a plain HTML table and adds a lot of JavaScript functionalities. It has a lot of additional features such as Excel-like navigation through the table, inline cell editing, column reordering, etc. One of the features that is provided is row drag and drop. In this article, I will explain how you can use the jQuery DataTables drag and drop feature in your ASP.NET MVC application.

Background

This article is part of a series about integration of the jQuery DataTables plug-in with ASP.NET MVC web applications. You might also want to take a look at other articles in this group:

  1. jQuery DataTables and ASP.NET MVC Integration
  2. ASP.NET MVC Editable Table
  3. Refreshing the content of DataTable using AJAX in ASP.NET MVC
  4. Creating an expandable master-details table
  5. jQuery DataTables Advanced Filtering in ASP.NET MVC

In these articles, you might find a lot of useful information about the usage of the jQuery DataTables plug-in in ASP.NET MVC. If you have not read the first article, I would recommend that you read it too because it contains some important details about the basic integration of jQuery DataTables with ASP.NET MVC applications.

jQuery DataTables is an excellent jQuery plug-in that enables you to display and manage information in a table. Detailed instructions about integrating the jQuery DataTables plug-in in an ASP.NET MVC application is described in the "jQuery DataTables and ASP.NET MVC Integration" article, but here I will shortly summarize how you can integrate this plug-in.

First, you will need to place a plain HTML table in the page. An example of a table is shown in the following code:

<table class="display" id="example">
    <thead>
        <tr>
            <th>OrderIndex</th><th>Name</th><th>Address</th><th>Town</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td><td>Gowi</td><td>Town</td><td>Pancevo</td>
        </tr>
        <tr>
            <td>2</td><td>Microsoft</td><td></td><td>Redmond</td>
        </tr>
        <tr>
            <td>3</td><td>IBM</td><td></td><td></td>
        </tr>
        <tr>
            <td>4</td><td>Oracle</td><td></td><td></td>
        </tr>
    </tbody>
</table>

This will be generated as a standard web table - very similar to the one on the following figure:

Then you will need to bind the table with the plug-in. This is done using the following jQuery call:

<script type="text/javascript" charset="utf-8">
$(document).ready( function () {
      $('#example').dataTable();
});
</script>

As a result, you will get a fully functional table with pagination, sorting, and filtering as shown in the following figure:

As you can see, only oe line of JavaScript code is required to enhance a plain table with advanced sorting, filtering, and pagination functionalities. The goal of this article is to show how you can implement reordering table rows using drag and drop on top of these functionalities.

Using the code

The code is organized in a standard Model-View-Controller architecture.

Model

The Model comes to a simple class containing company data. The fields that we need are company ID, name, address, and town. Also, each company object contains a unique order index information. Companies will be ordered by this index in the view. The source code of the company model class is shown below:

public class Company
{
    public int ID { get; set; }
    public int OrderIndex{ get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public string Town { get; set; }
}

View

Since the data presentation is done on the client-side, the classic View page is fairly simple. It contains a simple HTML table "decorated" with the jQuery DataTables plug-in. For example:

@{
    Layout = null;
}

<!DOCTYPE html>
<html>    
    <head>   
        <title>jQuery DataTables/ASP.NET MVC Row Reordering</title>
        <link href="/Content/dataTables/demo_table.css" rel="stylesheet" type="text/css" />        
        <script src="/Scripts/jQuery-1.5.1.min.js" type="text/javascript"></script>
        <script src="/Scripts/jQuery-ui-1.8.11.min.js" type="text/javascript"></script>
        <script src="/Scripts/jQuery.dataTables.min.js" type="text/javascript"></script>
        <script src="/Scripts/jQuery.dataTables.rowReordering.js" type="text/javascript"></script>
        <script type="text/javascript">
        $(document).ready(function () {
                 $('#myDataTable').dataTable();
        });
        </script>
    </head>
    <body>
                <table id="myDataTable" class="display">
                    <thead>
                        <tr>
                            <th></th>
                            <th>Company name</th>
                            <th>Address</th>
                            <th>Town</th>
                        </tr>
                    </thead>
                    <tbody> 
                    @foreach(var company in Model) {
                        <tr id="@company.ID">
                            <tr>@company.OrderIndex</tr>
                            <tr>@company.Name</tr>
                            <tr>@company.Address</tr>
                            <tr>@company.Town</tr>
                        </tr>
                    }
                    </tbody>
                </table>
    </body>
</html>

The assumption is that the controller has passed an enumeration of companies to view.

The View generates a valid HTML table according to the jQuery DataTables requirements. Additionally, this View places the ID of each company as an ID attribute of rows, and the order index in the first column. This is not required for the jQuery DataTables plug-in, but this information will be used to determine what row is moved on some position.

Also, as part of the View we would need to initialize a table with the jQuery DataTables plug-in. This initialization script will add standard DataTables features (pagination, filtering by keyword, and sorting).

Controller

The Controller in this example has two functions - to provide an initial list of companies that will be displayed in the table and to update the order of companies once they are reordered by the user.

The first functionality is fairly simple - it should just pass a list of companies to view. This controller action is shown in the following listing:

public class Controller
{
    public ActionResult Index()
    {
        return View(DataRepository.GetCompanies());
    }
}

The second function is shown in the next section.

Implement row reordering

Now we have a table with all enhancements and we want to add row reordering. The implementation of reordering is simple: an additional call needs to be done in the DataTable initialization:

$(document).ready(function () {              
    $('#myDataTable').dataTable().rowReordering();
});

Once the rowReordering add-on is applied, you will be able to sort the rows in the table using drag'n'drop functionality. The plug-in itself will manage row positions and update the indexing column. Note that sorting in the table is disabled by the add-on because rows will need to be ordered by the order index column. In the following figure you can see how reordering works:

As you can see, jQuery UI sortable is applied on the table rows. Each time a row is moved, the plug-in will update the order index numbers.

There are a lot of options that can be used to configure the plug-in - you can see other options on the jQuery DataTables Row Reordering wiki.

Updating an order on the server-side

Updating an order on the web page is not very useful if you do not persist the changes. Therefore, the row reordering plug-in allows you to send information about

<script type="text/javascript">
    $(document).ready(function () {
        $('#myDataTable').dataTable().rowReordering({ sURL: "/Company/UpdateOrder" });
    });
</script>

Each time rows are reordered, the plug-in will send an AJAX request with the following information:

  • id - the ID of the row that is moved. This ID is placed in the ID attribute of the table row (TR) that is moved.
  • fromPosition - the initial position of the row
  • toPosition - position where the row is dropped
  • direction - back or forward

The plug-in will update the order indexes in the table, and the Controller that accepts these parameters should update the order on the server-side. This controller action is shown in the following listing:

public void UpdateOrder(int id, int fromPosition, int toPosition, string direction)
{
    if (direction == "back")
    {
        var movedCompanies = DataRepository.GetCompanies()
                    .Where(c => (toPosition <= c.OrderIndex && c.OrderIndex <= fromPosition))
                    .ToList();

        foreach (var company in movedCompanies)
        {
            company.OrderIndex++;
        }
    }
    else
    {
        var movedCompanies = DataRepository.GetCompanies()
                    .Where(c => (fromPosition <= c.OrderIndex && c.OrderIndex <= toPosition))
                    .ToList();
        foreach (var company in movedCompanies)
        {
            company.OrderIndex--;
        }
    }

    DataRepository.GetCompanies().First(c => c.ID == id).OrderIndex = toPosition;
}

In this method, order indexes will be moved back or forward depending on the direction. As a result, the order index will be synchronized on both sides. In this example, I have used an in-memory list of objects, but in a real case you will probably update the order indexes in the database.

Conclusion

In this article I have explained how you can implement reordering of rows in a table. As you can see you need minimal effort on the View side - just a plain table and simple JavaScript that can be easily changed.

The plug-in will handle everything for you on the client side and all you need to do is to create a controller action method that will handle AJAX calls sent by the plug-in and update the order on the server side too.

You can see other features of the row reordering plug-in on the plug-in site.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Jovan Popovic
Architect Gowi
Serbia Serbia
Started as a young scientist - winning the highest national awards in mathematics, physics, electrotechnics, and electronics.
Graduated from Faculty of Electrical Engineering, Department of Computer Techniques and Informatics, University of Belgrade, Serbia, as a first in the class, as a Master of Software Sciences.
Currently working in Gowi as a Software engineer, architect, and project manager since 2004 - mostly using Microsoft technologies (ASP.NET, C#). Member of JQuery community - created few popular plugins (four popular JQuery DataTables add-ins and loadJSON template engine).
Interests: Software engineering process(estimation and standardization), mobile and business intelligence platforms.

Comments and Discussions

 
QuestionMy vote of 5 PinmemberNeha Kochhar Dixit1-Aug-14 9:32 
QuestionI don't have a Data Repository. Please Help. PinmemberMember 1090430224-Jun-14 18:29 
What if I don't have a Data Repository? My Project is directly connected to a Database from SQL Server. The Model I'm using is shown below. The table I want to order is ProductionOrder.cs
 
Models
 >DBModel.edmx
  >ProductionOrder.cs
 
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace SchneiderDMS.Models
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.ComponentModel.DataAnnotations;
    
    //public partial class ProductionOrder
    public class ProductionOrder
    {
        public ProductionOrder()
        {
            this.ProductionOrderBoxes = new HashSet<ProductionOrderBox>();
        }
    
        public int ID { get; set; }
        public Nullable<int> Priority { get; set; }
        public string ProductionOrderNumber { get; set; }
        public Nullable<int> LineID { get; set; }
        public Nullable<decimal> Quantity { get; set; }
 
        public Nullable<int> ProductionOrderStatusID { get; set; }
        public Nullable<int> SalesOrderID { get; set; }
    
        public virtual Line Line { get; set; }
        public virtual ProductionOrderStatu ProductionOrderStatu { get; set; }
        public virtual SalesOrder SalesOrder { get; set; }
        public virtual ICollection<ProductionOrderBox> ProductionOrderBoxes { get; set; }
    }
}
 

 
What do I use or type in instead of
Return View(DataRepository.GetCompanies())
 

And I want to use Priority field as the OrderIndex of your example. So I only change OrderIndex to Priority right?
 
        public void UpdateOrder(int id, int fromPosition, int toPosition, string direction)
        {
            if (direction == "back")
            {
                var movedPOs = DataRepository.GetCompanies()
                            .Where(c => (toPosition <= c.Priority && c.Priority <= fromPosition))
                            .ToList();
 
                foreach (var PO in movedPOs)
                {
                    PO.Priority++;
                }
            }
            else
            {
                var movedPOs = DataRepository.GetCompanies()
                            .Where(c => (fromPosition <= c.Priority && c.Priority <= toPosition))
                            .ToList();
                foreach (var PO in movedPOs)
                {
                    PO.Priority--;
                }
            }
 
            DataRepository.GetCompanies().First(c => c.ID == id).Priority = toPosition;
 
        }

QuestionFile download does not work PinmemberAnil From The Alps17-Jun-13 19:21 
QuestionCall Row Drag & Drop plugin after the JSON object is loaded from the server PinmemberJan_Nemec25-Jun-12 1:45 
QuestionWhat if I wanted to nest the rows to one another Pinmembercrystal91547-May-12 7:35 
AnswerRe: What if I wanted to nest the rows to one another PinmvpJovan Popovic7-May-12 21:39 
Questioncan't open project in vs 2010 ultimate Pinmemberlouai19853-May-12 6:07 
AnswerRe: can't open project in vs 2010 ultimate PinmvpJovan Popovic3-May-12 6:13 
QuestionGreat article Pinmemberzyck25-Apr-12 13:45 
QuestionMy vote is 5 Pinmembermuhamd yusuf23-Apr-12 19:49 
AnswerRe: My vote is 5 PinmvpJovan Popovic24-Apr-12 21:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 23 Apr 2012
Article Copyright 2012 by Jovan Popovic
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid