Drag And Drop Data Between Two Tables In Angular Using HTML 5 Drag And Drop APIs

Introduction

Sometimes you need to drag and drop data from one table to another table in angular. In this article, I will show how we can drag and drop data between two tables in angular. Here, I am using HTML 5 Drag and Drop APIs to perform drag and drop action in angular.

I have created two tables, one is “Driver Schedule” which has driver schedule information and the other is “Trailer Info” which has trailer related information. Here the requirement is that I need to drag “Trailer No” from Trailer Info table and drop it into “Trailer No” column in Driver Schedule. And similarly, once you assign the trailer (using drag and drop from Trailer Info table to Driver Schedule) then you need to un-assign the trailer by performing drag and drop from Driver Schedule to Trailer Info.

Background

To make an object draggable set draggable=true on that element. Just about anything can be drag-enabled: images, files, links, files, or any markup on your page.

There are a number of different events to attach to for monitoring the entire drag and drop process.

  • dragstart
    The dragstart event is fired when the user starts dragging an element or text selection.
  • drop
    The drop event is fired when an element or text selection is dropped on a valid drop target.
  • dragleave
    The dragleave event is fired when a dragged element or text selection leaves a valid drop target.
  • dragover
    The dragover event is fired when an element or text selection is being dragged over a valid drop target .
  • dragend
    The dragend event is fired when a drag operation is being ended (by releasing a mouse button or hitting the escape key).

Installing Angular CLI

If you haven’t installed Angular CLI, you can do that by running the below command.

npm install -g @angular/cli

Generating a new project

We can use the below command to create a new project.

ng new DragAndDropDemo

 Now that we have created our application, let’s run it and see if it is working or not.

  1. ng serve --open (if you need to open the browser by the app)
  2. ng serve (if you want to manually open the browser).
  3. You can always use 'ng s' as well

The command will build your application and run it in the browser.

Create JSON Data Source for two tables

I have created two JSON files to bind the data in Driver Schedule and Trailer Info table.

schedule.json

Add JSON file with name “schedule.json” in the application. Add below JSON data code in this file.

{
    "data": [{
        "id": 1,
        "scheduleId": "Sch001",
        "driverName": "Anand",
        "origin": "Mumbai",
        "destination": "Delhi",
        "trailerNumber": "N/A"
    }, {
        "id": 2,
        "scheduleId": "Sch002",
        "driverName": "Rustam",
        "origin": "Mumbai",
        "destination": "Pune",
        "trailerNumber": "N/A"
    }, {
        "id": 3,
        "scheduleId": "Sch003",
        "driverName": "Ramesh",
        "origin": "Delhi",
        "destination": "Chennai",
        "trailerNumber": "N/A"
    }, {
        "id": 4,
        "scheduleId": "Sch004",
        "driverName": "Anuj",
        "origin": "Mumbai",
        "destination": "Chennai",
        "trailerNumber": "N/A"
    }, {
        "id": 5,
        "scheduleId": "Sch005",
        "driverName": "Kishor",
        "origin": "Mumbai",
        "destination": "Goa",
        "trailerNumber": "N/A"
    }, {
        "id": 6,
        "scheduleId": "Sch006",
        "driverName": "Suresh",
        "origin": "Mumbai",
        "destination": "Nashik",
        "trailerNumber": "N/A"
    }, {
        "id": 7,
        "scheduleId": "Sch007",
        "driverName": "Mahesh",
        "origin": "Delhi",
        "destination": "Luckmow",
        "trailerNumber": "N/A"
    }, {
        "id": 8,
        "scheduleId": "Sch008",
        "driverName": "Chandan",
        "origin": "Mumbai",
        "destination": "Jaipur",
        "trailerNumber": "N/A"
    }, {
        "id": 9,
        "scheduleId": "Sch009",
        "driverName": "Narendra",
        "origin": "Mumbai",
        "destination": "Banglore",
        "trailerNumber": "N/A"
    }, {
        "id": 10,
        "scheduleId": "Sch010",
        "driverName": "Jitendra",
        "origin": "Banglore",
        "destination": "Manglore",
        "trailerNumber": "N/A"
    }]
}

trailer.json

Add JSON file with name “trailer.json” in the application. Add below JSON data code in this file.

{
    "data": [{
        "trailerNumber": "Trl001",
        "origin": "Mumbai",
        "destination": "Delhi"
    }, {
        "trailerNumber": "Trl002",
        "origin": "Mumbai",
        "destination": "Pune"
    }, {
        "trailerNumber": "Trl003",
        "origin": "Delhi",
        "destination": "Chennai"
    }, {
        "trailerNumber": "Trl004",
        "origin": "Mumbai",
        "destination": "Chennai"
    }, {
        "trailerNumber": "Trl005",
        "origin": "Mumbai",
        "destination": "Goa"
    }, {
        "trailerNumber": "Trl006",
        "origin": "Mumbai",
        "destination": "Nashik"
    }, {
        "trailerNumber": "Trl007",
        "origin": "Delhi",
        "destination": "Luckmow"
    }]
}

Create Service

Create a service with name “app.service” to provide the data. Add below code in app.service file.

import{Injectable} from '@angular/core';
import * as ScheduleData from "./schedule.json";
import * as TrailerData from "./trailer.json";
@Injectable()
export class Service {
    constructor() {}
    getScheduleData() {
        return ScheduleData;
    }
    getTrailerData() {
        return TrailerData;
    }
}

If you look into above code, there are two lines of code as below. This code will Import the JSON data in app.service.

import * as ScheduleData from "./schedule.json";
import * as TrailerData from "./trailer.json";

To import the JSON data into angular, you need to set "resolveJsonModule": true in tsconfig.json file in compilerOptions section

Html Code

Add below code in app.component.html file

<div>
  <h2 style="text-align: center;"> Drag and Drop in Angular</h2>
</div>
<br />
<br />
<div class="Table">
  <div class="Row">
    <div class="Cell" style="width:50%;">
      <h2 style="text-align: center;">Driver Schedule </h2>
      <table>
        <thead>
          <th style="display: none;">ID</th>
          <th>Schedule ID</th>
          <th>Driver Name</th>
          <th>Origin</th>
          <th>Destination</th>
          <th>Trailer No</th>
        </thead>
        <tbody *ngFor="let sch of scheduleData ; let i=index;">
          <tr>
            <td style="display: none;">{{sch.id}}</td>
            <td>{{sch.scheduleId}}</td>
            <td>{{sch.driverName}}</td>
            <td>{{sch.origin}}</td>
            <td>{{sch.destination}}</td>
            <td class="trailerLink"  [draggable]="sch.trailerNumber!=='N/A'" (dragstart)="dragStartDriverSch($event, sch)" (drop)="onDropDriverSch($event, sch)"          (dragover)="onDragOver($event)" (dragleave)="onDragLeave($event)">{{sch.trailerNumber}}</td>
          </tr>
        </tbody>
      </table>
    </div>
    <div class="Cell" style="width:40%;">
      <h2 style="text-align: center;">Trailer Info</h2>
      <table (drop)="onDropToTrailer($event)">
        <thead>
          <th>Trailer No</th>
          <th>Origin</th>
          <th>Destination</th>
        </thead>
        <tbody *ngFor="let trl of trailerData ; let i=index;">
          <tr>
            <td  class="trailerLink" [draggable]="true" (dragstart)="dragStartTrailer($event, trl)"         (dragover)="onDragOver($event)" (dragleave)="onDragLeave($event)" (dragend)="onDragLeave($event)">{{trl.trailerNumber}}</td>
            <td>{{trl.origin}}</td>
            <td>{{trl.destination}}</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>

TS Code

Add below code in app.component.ts file

import {
    Component
} from '@angular/core';
import {
    Service
} from "./app.service";
@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
    providers: [Service]
})
export class AppComponent {
    sData: any;
    scheduleData;
    tData: any;
    trailerData;
    constructor(public service: Service) {}
    ngOnInit() {
        this.getScheduleData()
        this.getTrailerData();
    }
    getScheduleData() {
        this.sData = this.service.getScheduleData();
        this.scheduleData = this.sData.default.data;
    }
    getTrailerData() {
        this.tData = this.service.getTrailerData();
        this.trailerData = this.tData.default.data;
    }
    dragStartTrailer(event, data) {
        event.dataTransfer.setData("trailerData", JSON.stringify(data));
    }
    dragStartDriverSch(event, data) {
        let item = {
            'trailerNumber': data.trailerNumber,
            'origin': data.origin,
            'destination': data.destination,
        }
        event.dataTransfer.setData("DriverScheduleData", JSON.stringify(item));
    }
    onDropDriverSch(event, data) {
        if (event.dataTransfer.getData("trailerData")) {
            var trlData = JSON.parse(event.dataTransfer.getData("trailerData"));
            var sch = this.scheduleData.find(d => d.scheduleId == data.scheduleId);
            sch.trailerNumber = trlData.trailerNumber;
            var index = this.trailerData.findIndex(function(item, i) {
                return item.trailerNumber === trlData.trailerNumber
            });
            if (index > -1) {
                this.trailerData.splice(index, 1);
            }
        }
    }
    onDropToTrailer(event) {
        if (event.dataTransfer.getData("DriverScheduleData")) {
            var schData = JSON.parse(event.dataTransfer.getData("DriverScheduleData"));
            var sch = this.scheduleData.find(d => d.trailerNumber == schData.trailerNumber);
            sch.trailerNumber = 'N/A';
            this.trailerData.push(schData);
            this.trailerData.sort(function(a, b) {
                return a['trailerNumber'].localeCompare(b['trailerNumber']);
            });
        }
    }
    onDragOver(event) {
        event.stopPropagation();
        event.preventDefault();
    }
    onDragLeave(event) {
        event.stopPropagation();
        event.preventDefault();
    }
}

Now build and run the application. Please see the below demo to drag and drop the trailer.

Drag and drop data between two tables in angular using HTML 5 Drag and Drop APIs