Rearrange The Tasks List Dynamically By Drag And Drop Using Angular In MVC

Reorder the list of data via drag & drop feature and the current order of the list shall be persisted on the database.

Introduction

AngularJS is an MVC based framework. Google has developed Angular but it is an open source project that can be used freely and can be modified and shared by others.

Top features Of AngularJS

  • Two Way Data-Binding
    This means that any changes to the Model updates the View and any changes to the View updates the Model.

  • Dependency Injection
    AngularJS has a built-in Dependency Injection which makes applications easier to develop, maintain, and debug in addition to the test.

  • Testing
    Angular tests any of its code through both unit testing and end-to-end testing.

  • Model View Controller
    Split your application into MVC components. Maintaining these components and connecting them together means setting up Angular.
For more details, visit my article, Introduction To AngularJS In ASP.NET MVC.
 
Prerequisites
  • Visual Studio 2017 Version 15.7.3
  • Microsoft .NET Framework Version 4.7
  • Microsoft SQL Server 2016
  • SQL Server Management Studio v17.7
Description

In this project, I will show you the steps where reordering the item lists dynamically means when we drag and drop the item lists for changing the position at that time the order of items in the list will be reflected in the backend using AngularJS. I have used AngularJS directive that allows us to build sortable lists with the native HTML5 drag & drop API.

Implement Concept In Real Time
 
By using this concept we can implement it in our project for giving and modifying the priority of client requirements and itncan be assigned to developers as we are working in a ticket assigning tool by IBM or any other method
 
Steps To Be Followed
 
Step 1
 
Create a table named "MyTask" . You can find this table structure and insert records in this table from project folder.
 
Here I manually set the Order column value during page load by using the Items List or TaskDescription 
 
 
 
Step 2
 
Create an MVC application named "AngularDragDrop". Go to the file menu > New > projet > here select "asp.net web application (.Net Framework)" under web > enter application name "AngularDragDrop" > select your project location > and then click on OK button ... >

It will bring up a new dialog window for selecting template > here I will select MVC template > and the checked MVC checkbox from Add folder and core references > and then click on ok button.

Step 3

Then I have added Entity Data Model named "MyModel.edmx".

Go to Solution Explorer > Right Click on Project name from Solution Explorer > Add > New item > Select ADO.net Entity Data Model under data > Enter model name > Add. A popup window will come up (Entity Data Model Wizard) > Select Generate from database > Next >

Chose your data connection > select your database > next > Select tables "MyTask" > enter Model Namespace > Finish. 

Step 4

Inside HomeController I've added the following code.
 
Code Ref 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6.   
  7. namespace AngularDragDrop.Controllers  
  8. {  
  9.     public class HomeController : Controller  
  10.     {  
  11.         public ActionResult Index()  
  12.         {  
  13.             return View();  
  14.         }  
  15.   
  16.         public JsonResult GetTasks()  
  17.         {  
  18.             var tasks = new List<MyTask>();  
  19.             using (SatyaDBEntities dc = new SatyaDBEntities())  
  20.             {  
  21.                 tasks = dc.MyTasks.OrderBy(a => a.Order).ToList();  
  22.             }  
  23.             return new JsonResult { Data = tasks, JsonRequestBehavior = JsonRequestBehavior.AllowGet };  
  24.         }  
  25.   
  26.         public JsonResult SaveTaskOrder(List<MyTask> tasks)  
  27.         {  
  28.             bool status = false;  
  29.             using (SatyaDBEntities dc = new SatyaDBEntities())  
  30.             {  
  31.                 try  
  32.                 {  
  33.                     foreach (var i in tasks)  
  34.                     {  
  35.                         dc.MyTasks.Attach(i);  
  36.                         dc.Entry(i).State = System.Data.Entity.EntityState.Modified;  
  37.                     }  
  38.                     dc.SaveChanges();  
  39.                     status = true;  
  40.                 }  
  41.                 catch (Exception)  
  42.                 {  
  43.   
  44.                 }  
  45.             }  
  46.             return new JsonResult { Data = new { status = status } };  
  47.         }  
  48.   
  49.         public ActionResult About()  
  50.         {  
  51.             ViewBag.Message = "Your application description page.";  
  52.   
  53.             return View();  
  54.         }  
  55.   
  56.         public ActionResult Contact()  
  57.         {  
  58.             ViewBag.Message = "Your contact page.";  
  59.   
  60.             return View();  
  61.         }  
  62.     }  
  63. }  
Code Description
 
Here I have added code for fetching data from the database and returning as a JSON result.
  1. public JsonResult GetTasks()  
  2.         {  
  3.             var tasks = new List<MyTask>();  
  4.             using (SatyaDBEntities dc = new SatyaDBEntities())  
  5.             {  
  6.                 tasks = dc.MyTasks.OrderBy(a => a.Order).ToList();  
  7.             }  
  8.             return new JsonResult { Data = tasks, JsonRequestBehavior = JsonRequestBehavior.AllowGet };  
  9.         }  
In this MVC action "GetTasks()"  is for fetching MyTask table data from the database and returning as a JSON result for showing my tasks list priority wise. 
 
I have added another MVC action into HomeController for updating my tasks lists data with a new order to the database.
  1. public JsonResult SaveTaskOrder(List<MyTask> tasks)  
  2.         {  
  3.             bool status = false;  
  4.             using (SatyaDBEntities dc = new SatyaDBEntities())  
  5.             {  
  6.                 try  
  7.                 {  
  8.                     foreach (var i in tasks)  
  9.                     {  
  10.                         dc.MyTasks.Attach(i);  
  11.                         dc.Entry(i).State = System.Data.Entity.EntityState.Modified;  
  12.                     }  
  13.                     dc.SaveChanges();  
  14.                     status = true;  
  15.                 }  
  16.                 catch (Exception)  
  17.                 {  
  18.   
  19.                 }  
  20.             }  
  21.             return new JsonResult { Data = new { status = status } };  
  22.         }  
Here I use foreach loop to reorder the items list and update lists data with a new order to the database. The entity is being tracked by the context and exists in the database, and some or all of its property values have been modified and gets or sets the state of the entity. Then after foreach loop saves all changes made in this context to the underlying database.
  1. foreach (var i in tasks)  
  2.                     {  
  3.                         dc.MyTasks.Attach(i);  
  4.                         dc.Entry(i).State = System.Data.Entity.EntityState.Modified;  
  5.                     }  
  6.                     dc.SaveChanges();  
  7.                     status = true;  
Step 5
 
I have added necessary resource files into our project for "angular-drag-and-drop-lists" directive. We will use angular-drag-and-drop-lists directive for adding drag & drop sorting features
 
Here I have added the following files into our project
  • "angular-drag-and-drop-lists.js" file
  • "simple.css" file
angular-drag-and-drop-lists.js file will be available in Scripts folder and simple.css file will be available in Content folder of the project folder.
 
angular-drag-and-drop-lists.js
 
Angular directives allow you to build sortable lists with the native HTML5 drag & drop API. The directives can also be nested to bring drag & drop. The details about this script file and related attributes and css classes are described inside the script file with a green mark.
 
simple.css
 
Drag & drop the list items to move them around, or just click to select them. The details about this CSS file and related attributes and css classes are described inside the script file with a green mark.
  • Nested Lists
  • Simple Lists
  • Typed Lists
  • Advanced Features
  • Multiselection Demo
Step 6
 
I have added a Javascript file, where we will write AngularJS code for creating an Angular module and an Angular controller. Go to solution explorer > Right click on "Scripts" folder > Add > new Item > Select Javascrip file under Scripts > Enter file name (here in my application it is "myApp.js") > and then click on Add button.
 
Code Ref:
  1. var app = angular.module('myApp', ['dndLists']);  
  2. app.controller('myController', ['$http'function ($http) {  
  3.     var vm = this;  
  4.     vm.Tasks = [];  
  5.     vm.IsProcessing = false;  
  6.      
  7.     vm.LoadTask = function () {  
  8.         vm.IsProcessing = true;  
  9.         $http.get('/home/GetTasks').then(function (response) {  
  10.             vm.Tasks = response.data;  
  11.         }).finally(function () {  
  12.             vm.IsProcessing = false;  
  13.         })  
  14.     }  
  15.     vm.LoadTask();  
  16.        
  17.     vm.Sorting = function (index) {  
  18.         vm.IsProcessing = true;  
  19.         vm.Tasks.splice(index, 1);  
  20.         var newData = [];  
  21.         angular.forEach(vm.Tasks, function (val, index) {  
  22.             val.Order = index + 1;  
  23.             newData.push(val);  
  24.         })  
  25.   
  26.         //  
  27.         $http.post('/home/SaveTaskOrder', newData).then(function (response) {  
  28.               
  29.         }).finally(function () {  
  30.             vm.IsProcessing = false;  
  31.         })  
  32.     }  
  33.   
  34. }])  
Code Description:
 
Add a dependency to your application module.
  1. var app = angular.module('myApp', ['dndLists']);  
Here I created a module named myApp and registered a controller named myController and then added GetTasks controller action method of HomeController for fetching data from the database.
  1. vm.LoadTask = function () {  
  2.         vm.IsProcessing = true;  
  3.         $http.get('/home/GetTasks').then(function (response) {  
  4.             vm.Tasks = response.data;  
  5.         }).finally(function () {  
  6.             vm.IsProcessing = false;  
  7.         })  
  8.     }  
Update Tasks order after dragging and dropping the tasks list.
  1. vm.Sorting = function (index) {  
  2.        vm.IsProcessing = true;  
  3.        vm.Tasks.splice(index, 1);  
  4.        var newData = [];  
  5.        angular.forEach(vm.Tasks, function (val, index) {  
  6.            val.Order = index + 1;  
  7.            newData.push(val);  
  8.        })  
Another MVC action into HomeController for updating my tasks data with a new order to the database. 
  1. $http.post('/home/SaveTaskOrder', newData).then(function (response) {  
  2. }
Step 7
 
Now i have added a view for that Index action called "Index.cshtml". Right Click on Action Method (here right click on Index action) > Add View... > Enter View Name > Select "Empty" under Template dropdown > > Add.
 
Code Ref
  1. @{  
  2.     ViewBag.Title = "Satyaprakash-DragndDrop Using Angular";  
  3. }  
  4.   
  5. <div ng-app="myApp">  
  6.     <div ng-controller="myController as vm" class="simpleDemo">  
  7.         <h2 style="background-color: Yellow;color: Blue; text-align: center; font-style: oblique">Reordering list via drag & drop in AngularJS</h2>  
  8.         <div class="loader" ng-show="vm.IsProcessing">  
  9.             Please Wait...  
  10.         </div>  
  11.         <ul dnd-list="vm.Tasks">  
  12.             <li ng-repeat="item in vm.Tasks"  
  13.                 dnd-list-id="{{item.TaskID}}"  
  14.                 dnd-draggable="item"  
  15.                 dnd-moved="vm.Sorting($index)"  
  16.                 dnd-effect-allowed="move"  
  17.                 dnd-selected="models.selected = item"  
  18.                 ng-class="{'selected': models.selected === item}">  
  19.                 {{item.TaskDescription}}  
  20.             </li>  
  21.         </ul>  
  22.     </div>  
  23. </div>  
  24.   
  25. <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.js"></script>  
  26. <script src="~/Scripts/angular-drag-and-drop-lists.js"></script>  
  27. <script src="~/Scripts/myApp.js"></script>  
  28. <link href="~/Content/simple.css" rel="stylesheet" />  
  29. <style>  
  30.     .loader {  
  31.         position: absolute;  
  32.         z-index: 9;  
  33.         background: yellow;  
  34.         border: 1px solid red;  
  35.         padding: 10px;  
  36.         top: 50%;  
  37.         left: 20%;  
  38.     }  
  39.   
  40.     .simpleDemo {  
  41.         position: relative;  
  42.     }  
  43.   
  44.         .simpleDemo ul[dnd-list] li {  
  45.             cursor: move;  
  46.         }  
  47. </style>  
Code Description
 
Here module is named myApp and I registered a controller named myController.
  1. <div ng-app="myApp">  
  2.     <div ng-controller="myController as vm" class="simpleDemo">  
Here simpleDemo is the name of the css class inside a simple.css file. Here vm is an object of controller named myController  and by using this object we can access all properties and behavior of myController.
  1. <div class="loader" ng-show="vm.IsProcessing">  
  2.            Please Wait...  
  3.        </div>  
  4.        <ul dnd-list="vm.Tasks">  
  5.            <li ng-repeat="item in vm.Tasks"  
  6.                dnd-list-id="{{item.TaskID}}"  
  7.                dnd-draggable="item"  
  8.                dnd-moved="vm.Sorting($index)"  
  9.                dnd-effect-allowed="move"  
  10.                dnd-selected="models.selected = item"  
  11.                ng-class="{'selected': models.selected === item}">  
  12.                {{item.TaskDescription}}  
  13.            </li>  
  14.        </ul>  
Here I mentioned the loader which will get the data from the database and update the task order.
  1. <div class="loader" ng-show="vm.IsProcessing">  
  2.             Please Wait...  
  3.         </div>  
The dnd-list directive allows us  to drop elements into it. The dropped data will be added to the referenced list.
  1. <ul dnd-list="vm.Tasks">  
The dnd-draggable directive makes an element draggable and will transfer the object that was assigned to it. If an element was dragged away, you have to remove it from the original list yourself using the dnd-moved attribute.
  1. <ul dnd-list="vm.Tasks">  
  2.             <li ng-repeat="item in vm.Tasks"  
  3.                 dnd-list-id="{{item.TaskID}}"  
  4.                 dnd-draggable="item"  
  5.                 dnd-moved="vm.Sorting($index)"  
  6.                 dnd-effect-allowed="move"  
  7.                 dnd-selected="models.selected = item"  
  8.                 ng-class="{'selected': models.selected === item}">  
  9.                 {{item.TaskDescription}}  
  10.             </li>  
  11.         </ul>  
Here I have added CDN and local path reference of script file as well as css file for drag & drop sorting features. So we use these resources into our application for the directive.  
  1. <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.js"></script>  
  2. <script src="~/Scripts/angular-drag-and-drop-lists.js"></script>  
  3. <script src="~/Scripts/myApp.js"></script>  
  4. <link href="~/Content/simple.css" rel="stylesheet" />  
Here I manually added some css code for loader and task list format  for UI purposes.
  1. <style>  
  2.     .loader {  
  3.         positionabsolute;  
  4.         z-index9;  
  5.         background: yellow;  
  6.         border1px solid red;  
  7.         padding10px;  
  8.         top: 50%;  
  9.         left: 20%;  
  10.     }  
  11.   
  12.     .simpleDemo {  
  13.         positionrelative;  
  14.     }  
  15.   
  16.         .simpleDemo ul[dnd-list] li {  
  17.             cursormove;  
  18.         }  
  19. </style>  
Download Source Code
OUTPUT
 
During initial load or fetching data from database and updating the tasks order the loader will be shown like below.
 
 
 
According to the order value in the backend the tasks will be arranged accordingly.
 
 
Now the order of the tasks in Step 1 and Step 2 in the backend is 2 and 3 as shown below..
 
 
 
Now I changed the position of Step 1 and Step 2 to Order 1 and 2.
 
 
Now the Order of the tasks of Step 1 and Step 2 in the backend is 1 and 2 as shown below.
 
 
 
During drag and drop the tasks list in the UI will be shown as below..
 
 
SUMMARY
  • Angular-drag-and-drop-lists directive for adding drag & drop sorting features.
  • Reorder the tasks list dynamically.
  • AngularJS directive that allows us to build sortable lists with the native HTML5 drag & drop API.
  • Bootstrap UI support.