Angular 2 Drag-and-Drop without dependencies.
npm install ng2-dnd --save
Simple examples using ng2-dnd:
- with SystemJS in ng2-systemjs-demo
- with Webpack in ng2-webpack-demo
Online demo available here
If you use SystemJS to load your files, you might have to update your config with this if you don't use defaultJSExtensions: true
:
System.config({
packages: {
"/ng2-dnd": {"defaultExtension": "js"}
}
});
Finally, you can use ng2-dnd in your Angular 2 project:
- Import
DND_PROVIDERS, DND_DIRECTIVES
fromng2-dnd/ng2-dnd
; - Use
DND_PROVIDERS
in the bootstrap of your application; - Add
DND_DIRECTIVES
to thedirectives
property of your application component; - Use
dnd-draggable
anddnd-droppable
properties in template of your components.
import {Component} from 'angular2/core';
import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd';
import {bootstrap} from 'angular2/platform/browser';
bootstrap(AppComponent, [
DND_PROVIDERS // It is required to have 1 unique instance of your service
]);
@Component({
selector: 'app',
directives: [DND_DIRECTIVES],
template: `
<h4>Simple Drag-and-Drop</h4>
<div class="row">
<div class="col-sm-3">
<div class="panel panel-success">
<div class="panel-heading">Available to drag</div>
<div class="panel-body">
<div class="panel panel-default" dnd-draggable [dragEnabled]="true">
<div class="panel-body">
<div>Drag Me</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-3">
<div dnd-droppable class="panel panel-info">
<div class="panel-heading">Place to drop</div>
<div class="panel-body">
</div>
</div>
</div>
<div class="col-sm-3">
<div dnd-droppable class="panel panel-warning">
<div class="panel-heading">Restricted to drop</div>
<div class="panel-body">
</div>
</div>
</div>
</div>
`
})
export class AppComponent {
constructor() { }
}
You can use property dropZones (actually an array) to specify in which place you would like to drop the draggable element:
import {Component} from 'angular2/core';
import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd';
import {bootstrap} from 'angular2/platform/browser';
bootstrap(AppComponent, [
DND_PROVIDERS // It is required to have 1 unique instance of your service
]);
@Component({
selector: 'app',
directives: [DND_DIRECTIVES],
template: `
<h4>Restricting Drag-and-Drop with zones</h4>
<div class="row">
<div class="col-sm-3">
<div class="panel panel-primary">
<div class="panel-heading">Available to drag</div>
<div class="panel-body">
<div class="panel panel-default" dnd-draggable [dragEnabled]="true"
[dropZones]="['zone1']">
<div class="panel-body">
<div>Drag Me</div>
<div>Zone 1 only</div>
</div>
</div>
</div>
</div>
<div class="panel panel-success">
<div class="panel-heading">Available to drag</div>
<div class="panel-body">
<div class="panel panel-default" dnd-draggable [dragEnabled]="true"
[dropZones]="['zone1', 'zone2']">
<div class="panel-body">
<div>Drag Me</div>
<div>Zone 1 & 2</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-3">
<div dnd-droppable class="panel panel-info" [dropZones]="['zone1']">
<div class="panel-heading">Zone 1</div>
<div class="panel-body">
</div>
</div>
</div>
<div class="col-sm-3">
<div dnd-droppable class="panel panel-warning" [dropZones]="['zone2']">
<div class="panel-heading">Zone 2</div>
<div class="panel-body">
</div>
</div>
</div>
</div>
`
})
export class AppComponent {
constructor() { }
}
You can transfer data from draggable to droppable component via dragData property of Draggable component:
import {Component} from 'angular2/core';
import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd';
import {bootstrap} from 'angular2/platform/browser';
bootstrap(AppComponent, [
DND_PROVIDERS // It is required to have 1 unique instance of your service
]);
@Component({
selector: 'app',
directives: [DND_DIRECTIVES],
template: `
<h4>Transfer custom data in Drag-and-Drop</h4>
<div class="row">
<div class="col-sm-3">
<div class="panel panel-success">
<div class="panel-heading">Available to drag</div>
<div class="panel-body">
<div class="panel panel-default" dnd-draggable [dragEnabled]="true"
[dragData]="transferData">
<div class="panel-body">
<div>Drag Me</div>
<div>{{transferData | json}}</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-3">
<div dnd-droppable class="panel panel-info"
(onDropSuccess)="transferDataSuccess($event)">
<div class="panel-heading">Place to drop (Items:{{receivedData.length}})</div>
<div class="panel-body">
<div [hidden]="!receivedData.length > 0"
*ngFor="#data of receivedData">{{data | json}}</div>
</div>
</div>
</div>
</div>
`
})
export class AppComponent {
transferData:Object = {id:1, msg: 'Hello'};
receivedData:Array<any> = [];
constructor() { }
transferDataSuccess($event) {
this.receivedData.push($event);
}
}
Here is an example of shopping backet with products adding via drag and drop operation:
import {Component} from 'angular2/core';
import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd';
import {bootstrap} from 'angular2/platform/browser';
bootstrap(AppComponent, [
DND_PROVIDERS // It is required to have 1 unique instance of your service
]);
@Component({
selector: 'app',
directives: [DND_DIRECTIVES],
template: `
<h4>Shopping basket</h4>
<div class="row">
<div class="col-sm-3">
<div class="panel panel-success">
<div class="panel-heading">Available products</div>
<div class="panel-body">
<div *ngFor="#product of availableProducts" class="panel panel-default"
dnd-draggable [dragEnabled]="product.quantity>0" [dragData]="product"
(onDragSuccess)="orderedProduct($event)" [dropZones]="['demo1']">
<div class="panel-body">
<div [hidden]="product.quantity===0">{{product.name}} - \${{product.cost}}
<br>(available: {{product.quantity}})</div>
<div [hidden]="product.quantity>0"><del>{{product.name}}</del>
<br>(NOT available)</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-3">
<div dnd-droppable (onDropSuccess)="addToBasket($event)" [dropZones]="['demo1']"
class="panel panel-info">
<div class="panel-heading">Shopping Basket<br>(to pay: \${{totalCost()}})</div>
<div class="panel-body">
<div *ngFor="#product of shoppingBasket" class="panel panel-default">
<div class="panel-body">
{{product.name}}<br>(ordered: {{product.quantity}}
<br>cost: \${{product.cost * product.quantity}})
</div>
</div>
</div>
</div>
</div>
</div>
`
})
export class AppComponent {
availableProducts: Array<Product> = [];
shoppingBasket: Array<Product> = [];
constructor() {
this.availableProducts.push(new Product("Blue Shoes", 3, 35));
this.availableProducts.push(new Product("Good Jacket", 1, 90));
this.availableProducts.push(new Product("Red Shirt", 5, 12));
this.availableProducts.push(new Product("Blue Jeans", 4, 60));
}
orderedProduct(orderedProduct: Product) {
orderedProduct.quantity--;
}
addToBasket(newProduct: Product) {
for (let indx in this.shoppingBasket) {
let product:Product = this.shoppingBasket[indx];
if (product.name === newProduct.name) {
product.quantity++;
return;
}
}
this.shoppingBasket.push(new Product(newProduct.name, 1, newProduct.cost));
}
totalCost():number {
let cost:number = 0;
for (let indx in this.shoppingBasket) {
let product:Product = this.shoppingBasket[indx];
cost += (product.cost * product.quantity);
}
return cost;
}
}
Here is an example of simple sortable of favorite drinks moving in container via drag and drop operation:
import {Component} from 'angular2/core';
import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd';
import {bootstrap} from 'angular2/platform/browser';
bootstrap(AppComponent, [
DND_PROVIDERS // It is required to have 1 unique instance of your service
]);
@Component({
selector: 'app',
directives: [DND_DIRECTIVES],
template: `
<h4>Simple sortable</h4>
<div class="row">
<div class="col-sm-3">
<div class="panel panel-success">
<div class="panel-heading">
Favorite drinks
</div>
<div class="panel-body">
<ul class="list-group" dnd-sortable-container [sortableData]="listOne">
<li *ngFor="#item of listOne; #i = index" class="list-group-item" dnd-sortable [sortableIndex]="i">{{item}}</li>
</ul>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-body">
My prefences:<br/>
<span *ngFor="#item of listOne; #i = index">{{i + 1}}) {{item}}<br/></span>
</div>
</div>
</div>
</div>`
})
export class AppComponent {
listOne:Array<string> = ['Coffee','Orange Juice','Red Wine','Unhealty drink!','Water'];
}
Here is an example of multi list sortable of boxers moving in container and between containers via drag and drop operation:
import {Component} from 'angular2/core';
import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd';
import {bootstrap} from 'angular2/platform/browser';
bootstrap(AppComponent, [
DND_PROVIDERS // It is required to have 1 unique instance of your service
]);
@Component({
selector: 'app',
directives: [DND_DIRECTIVES],
template: `
<h4>Multi list sortable</h4>
<div class="row">
<div class="col-sm-3">
<div class="panel panel-warning">
<div class="panel-heading">
Available boxers
</div>
<div class="panel-body" dnd-sortable-container [dropZones]="['boxers-zone']" [sortableData]="listBoxers">
<ul class="list-group" >
<li *ngFor="#item of listBoxers; #i = index" class="list-group-item" dnd-sortable [sortableIndex]="i">{{item}}</li>
</ul>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="panel panel-success">
<div class="panel-heading">
First Team
</div>
<div class="panel-body" dnd-sortable-container [dropZones]="['boxers-zone']" [sortableData]="listTeamOne">
<ul class="list-group" >
<li *ngFor="#item of listTeamOne; #i = index" class="list-group-item" dnd-sortable [sortableIndex]="i">{{item}}</li>
</ul>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="panel panel-info">
<div class="panel-heading">
Second Team
</div>
<div class="panel-body" dnd-sortable-container [dropZones]="['boxers-zone']" [sortableData]="listTeamTwo">
<ul class="list-group">
<li *ngFor="#item of listTeamTwo; #i = index" class="list-group-item" dnd-sortable [sortableIndex]="i">{{item}}</li>
</ul>
</div>
</div>
</div>
</div>`
})
export class AppComponent {
listBoxers:Array<string> = ['Sugar Ray Robinson','Muhammad Ali','George Foreman','Joe Frazier','Jake LaMotta','Joe Louis','Jack Dempsey','Rocky Marciano','Mike Tyson','Oscar De La Hoya'];
listTeamOne:Array<string> = [];
listTeamTwo:Array<string> = [];
}