Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/akserg/ng2-dnd
Angular 2 Drag-and-Drop without dependencies
https://github.com/akserg/ng2-dnd
angular angular2 angular4 drag drag-and-drop drop dropzone
Last synced: 1 day ago
JSON representation
Angular 2 Drag-and-Drop without dependencies
- Host: GitHub
- URL: https://github.com/akserg/ng2-dnd
- Owner: akserg
- License: mit
- Created: 2016-03-10T15:01:36.000Z (almost 9 years ago)
- Default Branch: master
- Last Pushed: 2023-01-08T16:27:01.000Z (about 2 years ago)
- Last Synced: 2025-01-17T13:08:49.949Z (8 days ago)
- Topics: angular, angular2, angular4, drag, drag-and-drop, drop, dropzone
- Language: TypeScript
- Size: 2.68 MB
- Stars: 838
- Watchers: 44
- Forks: 250
- Open Issues: 208
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
- awesome-angular-components - ng2-dnd - Angular 2 Drag-and-Drop without dependencies. (Uncategorized / Uncategorized)
- awesome-angular - ng2-dnd - Angular 2 Drag-and-Drop without dependencies. (Uncategorized / Uncategorized)
- awesome-angular-components - ng2-dnd - Angular 2 Drag-and-Drop without dependencies (Uncategorized / Uncategorized)
- awesome-angular-components - ng2-dnd - Angular 2 Drag-and-Drop without dependencies. (Uncategorized / Uncategorized)
README
# Angular 2 Drag-and-Drop [![npm version](https://badge.fury.io/js/ng2-dnd.svg)](https://badge.fury.io/js/ng2-dnd) [![npm monthly downloads](https://img.shields.io/npm/dm/ng2-dnd.svg?style=flat-square)](https://www.npmjs.com/package/ng2-dnd)
Angular 2 Drag-and-Drop without dependencies.Follow me [![twitter](https://img.shields.io/twitter/follow/akopkokhyants.svg?style=social&label=%20akopkokhyants)](https://twitter.com/akopkokhyants) to be notified about new releases.
[![Build Status](https://travis-ci.org/akserg/ng2-dnd.svg?branch=master)](https://travis-ci.org/akserg/ng2-dnd)
[![Dependency Status](https://david-dm.org/akserg/ng2-dnd.svg)](https://david-dm.org/akserg/ng2-dnd)
[![devDependency Status](https://david-dm.org/akserg/ng2-dnd/dev-status.svg)](https://david-dm.org/akserg/ng2-dnd#info=devDependencies)
[![Known Vulnerabilities](https://snyk.io/test/github/akserg/ng2-dnd/badge.svg)](https://snyk.io/test/github/akserg/ng2-dnd)_Some of these APIs and Components are not final and are subject to change!_
## Transpilation to Angular Package Format
The library uses [ng-packagr](https://github.com/dherges/ng-packagr) to transpile into the Angular Package Format:
- Bundles library in `FESM2015`, `FESM5`, and `UMD` formats
- The npm package can be consumed by `Angular CLI`, `Webpack`, or `SystemJS`
- Creates type definitions (`.d.ts`)
- Generates Ahead-of-Time metadata (`.metadata.json`)
- Auto-discovers and bundles secondary entry points such as `@my/foo`, `@my/foo/testing`, `@my/foo/bar`## Installation
```bash
npm install ng2-dnd --save
```## Demo
- Webpack demo available [here](https://angular-dxqjhj.stackblitz.io)
- SystemJS demo available [here](http://embed.plnkr.co/JbG8Si)## Usage
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: `Simple Drag-and-Drop
`
Available to drag
Drag Me
Place to drop
Item was dropped here
})
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: `Simple Drag-and-Drop with handle
`
Available to drag
=
Drag Handle
Place to drop
Item was dropped here
})
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: `Restricted Drag-and-Drop with zones
`
Available to drag
Drag Me
Zone 1 only
Available to drag
Drag Me
Zone 1 & 2
Zone 1
Item was dropped here
Zone 2
Item was dropped here
})
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: `Transfer custom data in Drag-and-Drop
`
Available to drag
Drag Me
{{transferData | json}}
Place to drop (Items:{{receivedData.length}})
0" *ngFor="let data of receivedData">{{data | json}}
})
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 `dropZone`s 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. `dropZone`s 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: `Use a custom function to determine where dropping is allowed
Available to drag
dragData = 6
dragData = 10
dragData = 30
allowDropFunction(baseInteger: any): any {{ '{' }}
return (dragData: any) => dragData % baseInteger === 0;
{{ '}' }}
Multiples of
only
dragData = {{item}}
Multiples of
only
dragData = {{item}}
`
})
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: `Drag-and-Drop - Shopping basket
`
Available products
0" [dragData]="product" (onDragSuccess)="orderedProduct($event)" [dropZones]="['demo1']">
{{product.name}} - \${{product.cost}}
(available: {{product.quantity}})
0">{{product.name}}
(NOT available)
Shopping Basket
(to pay: \${{totalCost()}})
{{product.name}}
(ordered: {{product.quantity}}
cost: \${{product.cost * product.quantity}})
})
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: `Simple sortable
`
Favorite drinks
- {{item}}
My prefences:
{{i + 1}}) {{item}}
})
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: `Simple sortable handle
`
Favorite drinks
=
{{item}}
My prefences:
{{i + 1}}) {{item}}
})
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: `Simple sortable With Drop into recycle bin
`
Favorite drinks
- {{item}}
Recycle bin: Drag into me to delete it
Recycled: {{listRecycled.toString()}}
})
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: `Simple sortable With Drop into something, without delete it
`
Source List
- {{source.name}}
Target List
{{target.name}}
})
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: `Move items between multi list sortable containers
`
Drag Containers
{{container.id}} - {{container.name}}
- {{widget.name}}
Widgets
{{widget.name}}
})
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: `Simple FormArray sortable
`
Favorite drinks
My prefences:
{{i + 1}}) {{item.value}}
})
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: `Simple Drag-and-Drop
>
Place to drop
`
})
export class AppComponent {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));
});
}
}
}
}# Credits
- [Francesco Cina](https://github.com/ufoscout)
- [Valerii Kuznetsov](https://github.com/solival)
- [Shane Oborn](https://github.com/obosha)
- [Juergen Gutsch](https://github.com/JuergenGutsch)
- [Damjan Cilenšek](https://github.com/loudandwicked)# License
[MIT](/LICENSE)