Angular 2 Drag-and-Drop without dependencies
npm install ng2-dndFollow me  to be notified about new releases.




_Some of these APIs and Components are not final and are subject to change!_
FESM2015, FESM5, and UMD formatsAngular CLI, Webpack, or SystemJS.d.ts).metadata.json)@my/foo, @my/foo/testing, @my/foo/barbash
npm install ng2-dnd --save
`Demo
- Webpack demo available here
- SystemJS demo available hereUsage
If you use SystemJS to load your files, you might have to update your config:`js
System.config({
map: {
'ng2-dnd': 'node_modules/ng2-dnd/bundles/ng2-dnd.umd.js'
}
});
`#### 1. Add the default styles
- Import the
style.css into your web page from node_modules/ng2-dnd/bundles/style.css#### 2. Import the
DndModule
Import DndModule.forRoot() in the NgModule of your application.
The forRoot method is a convention for modules that provide a singleton service.`ts
import {BrowserModule} from "@angular/platform-browser";
import {NgModule} from '@angular/core';
import {DndModule} from 'ng2-dnd';@NgModule({
imports: [
BrowserModule,
DndModule.forRoot()
],
bootstrap: [AppComponent]
})
export class AppModule {
}
`If you have multiple NgModules and you use one as a shared NgModule (that you import in all of your other NgModules),
don't forget that you can use it to export the
DndModule that you imported in order to avoid having to import it multiple times.`ts
@NgModule({
imports: [
BrowserModule,
DndModule
],
exports: [BrowserModule, DndModule],
})
export class SharedModule {
}
`#### 3. Use Drag-and-Drop operations with no code
`js
import {Component} from '@angular/core';@Component({
selector: 'simple-dnd',
template:
})
export class SimpleDndComponent {
simpleDrop: any = null;
}
`#### 4. Add handle to restrict draggable zone of component
`js
import {Component} from '@angular/core';@Component({
selector: 'simple-dnd-handle',
template:
})
export class SimpleDndHandleComponent {
simpleDrop: any = null;
}
`#### 5. Restriction Drag-and-Drop operations with drop zones
You can use property dropZones (actually an array) to specify in which place you would like to drop the draggable element:
`js
import {Component} from '@angular/core';@Component({
selector: 'zone-dnd',
template:
})
export class ZoneDndComponent {
restrictedDrop1: any = null;
restrictedDrop2: any = null;
}
`#### 6. Transfer custom data via Drag-and-Drop
You can transfer data from draggable to droppable component via dragData property of Draggable component:
`js
import {Component} from '@angular/core';@Component({
selector: 'custom-data-dnd',
template:
})
export class CustomDataDndComponent {
transferData: Object = {id: 1, msg: 'Hello'};
receivedData: Array = []; transferDataSuccess($event: any) {
this.receivedData.push($event);
}
}
`#### 7. Use a custom function to determine where dropping is allowed
For use-cases when a static set of
dropZones is not possible, a custom function can be used to dynamically determine whether an item can be dropped or not. To achieve that, set the allowDrop property to this boolean function.In the following example, we have two containers that only accept numbers that are multiples of a user-input base integer.
dropZones are not helpful here because they are static, whereas the user input is dynamic.`js
import { Component } from '@angular/core';@Component({
selector: 'custom-function-dnd',
template:
allowDropFunction(baseInteger: any): any {{ '{' }}
return (dragData: any) => dragData % baseInteger === 0;
{{ '}' }}
})
export class CustomFunctionDndComponent {
box1Integer: number = 3;
box2Integer: number = 10; box1Items: string[] = [];
box2Items: string[] = [];
allowDropFunction(baseInteger: number): any {
return (dragData: any) => dragData % baseInteger === 0;
}
addTobox1Items($event: any) {
this.box1Items.push($event.dragData);
}
addTobox2Items($event: any) {
this.box2Items.push($event.dragData);
}
}
`#### 8. Shopping basket with Drag-and-Drop
Here is an example of shopping backet with products adding via drag and drop operation:
`js
import { Component } from '@angular/core';@Component({
selector: 'shoping-basket-dnd',
template:
})
export class ShoppingBasketDndComponent {
availableProducts: Array = [];
shoppingBasket: Array = []; 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($event: any) {
let orderedProduct: Product = $event.dragData;
orderedProduct.quantity--;
}
addToBasket($event: any) {
let newProduct: Product = $event.dragData;
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));
this.shoppingBasket.sort((a: Product, b: Product) => {
return a.name.localeCompare(b.name);
});
}
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;
}
}
class Product {
constructor(public name: string, public quantity: number, public cost: number) {}
}
`#### 9. Simple sortable with Drag-and-Drop
Here is an example of simple sortable of favorite drinks moving in container via drag and drop operation:
`js
import {Component} from '@angular/core';@Component({
selector: 'simple-sortable',
template:
})
export class SimpleSortableComponent {
listOne: Array = ['Coffee', 'Orange Juice', 'Red Wine', 'Unhealty drink!', 'Water'];
}
`
#### 10. Simple sortable with Drag-and-Drop handle
Add handle to restict grip zone of sortable component.
`js
import {Component} from '@angular/core';@Component({
selector: 'simple-sortable-handle',
template:
})
export class SimpleSortableHandleComponent {
listOne: Array = ['Coffee', 'Orange Juice', 'Red Wine', 'Unhealty drink!', 'Water'];
}
`#### 11. Simple sortable With Drop into recycle bin
Here is an example of multi list sortable of boxers moving in container and between containers via drag and drop operation:
`js
import {Component} from '@angular/core';@Component({
selector: 'recycle-multi-sortable',
template:
})
export class RecycleMultiSortableComponent {
listOne: Array = ['Coffee', 'Orange Juice', 'Red Wine', 'Unhealty drink!', 'Water'];
listRecycled: Array = [];
}
`#### 12. Simple sortable With Drop into something, without delete it
Here is an example of simple sortable list of items copying in target container:
`js
import {Component} from '@angular/core';@Component({
selector: 'simple-sortable-copy',
template:
})
export class SimpleSortableCopyComponent { sourceList: Widget[] = [
new Widget('1'), new Widget('2'),
new Widget('3'), new Widget('4'),
new Widget('5'), new Widget('6')
];
targetList: Widget[] = [];
addTo($event: any) {
this.targetList.push($event.dragData);
}
}
class Widget {
constructor(public name: string) {}
}
`#### 13. Multi list sortable between containers
Here is an example of multi list sortable of boxers moving in container and between containers via drag and drop operation:
`js
import {Component} from '@angular/core';@Component({
selector: 'embedded-sortable',
template:
})
export class EmbeddedSortableComponent {
dragOperation: boolean = false; containers: Array = [
new Container(1, 'Container 1', [new Widget('1'), new Widget('2')]),
new Container(2, 'Container 2', [new Widget('3'), new Widget('4')]),
new Container(3, 'Container 3', [new Widget('5'), new Widget('6')])
];
widgets: Array = [];
addTo($event: any) {
if ($event) {
this.widgets.push($event.dragData);
}
}
}
class Container {
constructor(public id: number, public name: string, public widgets: Array) {}
}
class Widget {
constructor(public name: string) {}
}
`#### 14. Simple FormArray sortable with Drag-and-Drop
Here is an example of simple sortable of favorite drinks moving in container via drag and drop operation but using FormArray instead of Array:
`js
import {Component} from '@angular/core';
import {FormArray, FormControl} from '@angular/forms';@Component({
selector: 'simple-formarray-sortable',
template:
})
export class SimpleFormArraySortableComponent {
listOne: FormArray = new FormArray([
new FormControl('Coffee'),
new FormControl('Orange Juice'),
new FormControl('Red Wine'),
new FormControl('Unhealty drink!'),
new FormControl('Water')
]);
}
`How to pass multiple data in dragData while dragging ?
1) As an array:
` html
[dragData]="[aComponent,'component-in-bar']"
`` javascript
loadComponent($event){
console.log($event.dragData[0]); // aComponent
console.log($event.dragData[1]); // 'component-in-bar' OR 'component-in-designer'
}
`2) As an object:
` html
[dragData]="{component: aComponent, location: 'component-in-bar'}"
`` javascript
loadComponent($event){
console.log($event.dragData.component); // aComponent
console.log($event.dragData.location); // 'component-in-bar' OR 'component-in-designer'
}
`Retreiving files in a drop zone
Since it is possible to drag and drop one or more files to a drop zone, you need to handle the incoming files.
`js
import {Component} from '@angular/core';
import {Http, Headers} from '@angular/http';
import {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd';
import {bootstrap} from '@angular/platform-browser-dynamic';bootstrap(AppComponent, [
DND_PROVIDERS // It is required to have 1 unique instance of your service
]);
@Component({
selector: 'app',
directives: [DND_DIRECTIVES],
template:
constructor(private _http: Http) { }
/**
* The $event is a structure:
* {
* dragData: any,
* mouseEvent: MouseEvent
* }
*/
transferDataSuccess($event) {
// let attachmentUploadUrl = 'assets/data/offerspec/offerspec.json';
// loading the FileList from the dataTransfer
let dataTransfer: DataTransfer = $event.mouseEvent.dataTransfer;
if (dataTransfer && dataTransfer.files) {
// needed to support posting binaries and usual form values
let headers = new Headers();
headers.append('Content-Type', 'multipart/form-data');
let files: FileList = dataTransfer.files;
// uploading the files one by one asynchrounusly
for (let i = 0; i < files.length; i++) {
let file: File = files[i];
// just for debugging
console.log('Name: ' + file.name + '\n Type: ' + file.type + '\n Size: ' + file.size + '\n Date: ' + file.lastModifiedDate);
// collecting the data to post
var data = new FormData();
data.append('file', file);
data.append('fileName', file.name);
data.append('fileSize', file.size);
data.append('fileType', file.type);
data.append('fileLastMod', file.lastModifiedDate);
// posting the data
this._http
.post(attachmentUploadUrl, data, {
headers: headers
})
.toPromise()
.catch(reason => {
console.log(JSON.stringify(reason));
});
}
}
}
}