How to Build Ionic 2 Drag and Drop using Dragula Last update: 2016-08-11

How to Build Ionic 2 Drag and Drop using Dragula

Having drag and drop functionality in your mobile app is very common, but it’s not really inlcuded in the standard Ionic stuff. I looked around and found a great library called Dragula which gives AngularJS apps great features.

This Tutorial was updated for Ionic 3.2!

Therefore today I will show you how to easily add drag and drop to your Ionic app by including and using ngDragula.

Prerequisite

Learning Ionic can become overwhelming, I know that feeling. Is learning from tutorials and videos sometimes not enough for you? Then I got something for you.

If you want to learn Ionic with step-by-step video courses, hands-on training projects and a helpful community who has your back, then take a look at the Ionic Academy.

Join the Ionic Academy

Setting up a blank app

As always we start with a blank Ionic app. We also already install the ng2-dragula library wich is the version of Dragula for Angular 2. So go ahead and run:

ionic start devdactic-drag blank
cd devdactic-drag
npm install ng2-dragula dragula --save

There are many great examples in the Dragula Demo, basically you can drag an item from one list/div to another defined area. You can also specify all kinds of attributes how the drag or drop feature should behave in special cases.

For us, we simply want to have 2 Ionic lists side by side and drag and drop items between those 2 lists.

To use Dragula we need to make sure it is imported to our module so change your src/app/app.module.ts to:

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

import { DragulaModule } from 'ng2-dragula';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    DragulaModule
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Importing and using ngDragula

To use the library we need to import it inside our class and add the directive and provider of ngDragula to our component.

Inside our class we have 2 arrays for our 2 lists. The lists will be filled with *ngFor, but the library will actually take care of moving the dragged item to the new array of our class, so all the data is updated.

Pretty awesome, right?

For an example we also subscribe to the drop event of the DragulaService and create a little alert. This means, whenever we drop something it should appear in the new place and also a popup should come up.

Now go ahead and insert in your app/pages/home/home.ts:

import { Component } from '@angular/core';
import { NavController, AlertController } from 'ionic-angular';
import { DragulaService } from 'ng2-dragula/ng2-dragula';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  q1 = [];
  q2 = [];

  constructor(private navController: NavController, public alertCtrl: AlertController, private dragulaService: DragulaService) {
    for (var i = 0; i < 20; i++) {
      this.q1.push("1. <" + i + ">");
      this.q2.push("2. <" + i + ">");
    }

    dragulaService.drop.subscribe((value) => {
      let alert = this.alertCtrl.create({
        title: 'Item moved',
        subTitle: 'So much fun!',
        buttons: ['OK']
      });
      alert.present();
    });
  }
}

That’s actually everything we need for our little demo to work with. Let’s craft the view around it.

Setting up our view for Drag and drop

As said before, we want to have 2 lists to drop from one to the other.

We give both our lists 50% width using the Ionic grid system.

For Dragula we actually need to define only 2 things:

  • [dragula]: The name of a general bag, should be the same for sources where you want to have drag and drop
  • [dragulaModel]: The actual array inside our class

Open the app/pages/home/home.html and insert:

<ion-header>
  <ion-navbar>
    <ion-title>
      Devdactic Drag & Drop
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
  <ion-row>
    <ion-col col-6 class="left">
      <div class="header">First Bucket</div>
      <ion-list [dragula]='"my-bag"' [dragulaModel]="q1">
        <button ion-item *ngFor="let item of q1" detail-none>
          {{item}}
      </button>
      </ion-list>
    </ion-col>

    <ion-col col-6 class="right">
      <div class="header">Second Bucket</div>
      <ion-list [dragula]='"my-bag"' [dragulaModel]="q2">
        <button ion-item *ngFor="let item of q2" detail-none>
          {{item}}
        </button>
      </ion-list>
    </ion-col>
  </ion-row>
</ion-content>

As you can see, we specify the name "my-bag" to let Dragula know those 2 lists have a connection, and for each list we specify either q1 or q2, the arrays from our previously created class.

Now this should already work, but to get the cool effects you might have seen on the Demo page we need to add some styling, which we can directly take from Dragula.

This is an important step, otherwise you might see no animation or working drag & drop at all!

The best way to do so is writing your own copy config for NPM packages, which I have described here.

Simply create the copy config, add it to your package.json and let it copy the file like this:

    copyDragulaCss: {
        src: './node_modules/dragula/dist/dragula.css',
        dest: '{{BUILD}}'
    }

Inside your index.html you can now use that file by loading it inside the header:

<link rel="stylesheet" href="build/dragula.css">

Now we got the animations, let’s finish it up with a few more classes for our own elements.

Adding finishing touches

These animations and stylings will add the effect of items floating above the rest while dragging and getting smooth into their new position. We also apply some own stylings to a few elements as well, so go ahead and insert in your app/pages/home/home.css:

page-home {
.header {
  height: 30px;
  padding-left: 5px;
  padding-top: 2px;
  text-align: center;
}

.left {
  border-right: 1px solid #000000;
  padding: 0px;
  overflow: scroll;
}

.right {
  padding: 0px;
  overflow: scroll;
}
}

Now go ahead and drag and drop all the items of your list!

Conclusion

It’s pretty easy to include a mighty feature like drag and drop with Ionic and Angular. If you found libraries like these that are already available with Angular 2+, you won’t have any problems most of the time. What are your experiences with other frameworks for animation or cool features? Let me know your experiences!

Happy Coding, Simon

Click below for a video version of this tutorial!