{"id":13481041,"url":"https://github.com/akserg/ng2-dnd","last_synced_at":"2025-05-15T06:03:44.912Z","repository":{"id":5627016,"uuid":"53593323","full_name":"akserg/ng2-dnd","owner":"akserg","description":"Angular 2 Drag-and-Drop without dependencies","archived":false,"fork":false,"pushed_at":"2023-01-08T16:27:01.000Z","size":2813,"stargazers_count":837,"open_issues_count":208,"forks_count":247,"subscribers_count":43,"default_branch":"master","last_synced_at":"2025-05-07T23:44:44.877Z","etag":null,"topics":["angular","angular2","angular4","drag","drag-and-drop","drop","dropzone"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/akserg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-03-10T15:01:36.000Z","updated_at":"2025-01-30T15:06:02.000Z","dependencies_parsed_at":"2023-01-13T13:37:41.899Z","dependency_job_id":null,"html_url":"https://github.com/akserg/ng2-dnd","commit_stats":null,"previous_names":[],"tags_count":42,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akserg%2Fng2-dnd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akserg%2Fng2-dnd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akserg%2Fng2-dnd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akserg%2Fng2-dnd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akserg","download_url":"https://codeload.github.com/akserg/ng2-dnd/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254198372,"owners_count":22030954,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","angular2","angular4","drag","drag-and-drop","drop","dropzone"],"created_at":"2024-07-31T17:00:48.014Z","updated_at":"2025-05-15T06:03:44.887Z","avatar_url":"https://github.com/akserg.png","language":"TypeScript","funding_links":[],"categories":["Uncategorized","Awesome Angular [![Awesome TipeIO](https://img.shields.io/badge/Awesome%20Angular-@TipeIO-6C6AE7.svg)](https://github.com/gdi2290/awesome-angular) [![Awesome devarchy.com](https://img.shields.io/badge/Awesome%20Angular-@devarchy.com-86BDC1.svg)](https://github.com/brillout/awesome-angular-components)"],"sub_categories":["Uncategorized","Angular \u003ca id=\"angular\"\u003e\u003c/a\u003e"],"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)\nAngular 2 Drag-and-Drop without dependencies.\n\nFollow me [![twitter](https://img.shields.io/twitter/follow/akopkokhyants.svg?style=social\u0026label=%20akopkokhyants)](https://twitter.com/akopkokhyants) to be notified about new releases.\n\n[![Build Status](https://travis-ci.org/akserg/ng2-dnd.svg?branch=master)](https://travis-ci.org/akserg/ng2-dnd)\n[![Dependency Status](https://david-dm.org/akserg/ng2-dnd.svg)](https://david-dm.org/akserg/ng2-dnd)\n[![devDependency Status](https://david-dm.org/akserg/ng2-dnd/dev-status.svg)](https://david-dm.org/akserg/ng2-dnd#info=devDependencies)\n[![Known Vulnerabilities](https://snyk.io/test/github/akserg/ng2-dnd/badge.svg)](https://snyk.io/test/github/akserg/ng2-dnd)\n\n_Some of these APIs and Components are not final and are subject to change!_\n\n## Transpilation to Angular Package Format\nThe library uses [ng-packagr](https://github.com/dherges/ng-packagr) to transpile into the Angular Package Format:\n- Bundles library in `FESM2015`, `FESM5`, and `UMD` formats\n- The npm package can be consumed by `Angular CLI`, `Webpack`, or `SystemJS`\n- Creates type definitions (`.d.ts`)\n- Generates Ahead-of-Time metadata (`.metadata.json`)\n- Auto-discovers and bundles secondary entry points such as `@my/foo`, `@my/foo/testing`, `@my/foo/bar`\n\n## Installation\n```bash\nnpm install ng2-dnd --save\n```\n\n## Demo\n- Webpack demo available [here](https://angular-dxqjhj.stackblitz.io)\n- SystemJS demo available [here](http://embed.plnkr.co/JbG8Si)\n\n## Usage\nIf you use SystemJS to load your files, you might have to update your config:\n\n```js\nSystem.config({\n    map: {\n        'ng2-dnd': 'node_modules/ng2-dnd/bundles/ng2-dnd.umd.js'\n    }\n});\n```\n\n#### 1. Add the default styles\n- Import the `style.css` into your web page from `node_modules/ng2-dnd/bundles/style.css`\n\n#### 2. Import the `DndModule`\nImport `DndModule.forRoot()` in the NgModule of your application. \nThe `forRoot` method is a convention for modules that provide a singleton service.\n\n```ts\nimport {BrowserModule} from \"@angular/platform-browser\";\nimport {NgModule} from '@angular/core';\nimport {DndModule} from 'ng2-dnd';\n\n@NgModule({\n    imports: [\n        BrowserModule,\n        DndModule.forRoot()\n    ],\n    bootstrap: [AppComponent]\n})\nexport class AppModule {\n}\n```\n\nIf you have multiple NgModules and you use one as a shared NgModule (that you import in all of your other NgModules), \ndon't forget that you can use it to export the `DndModule` that you imported in order to avoid having to import it multiple times.\n\n```ts\n@NgModule({\n    imports: [\n        BrowserModule,\n        DndModule\n    ],\n    exports: [BrowserModule, DndModule],\n})\nexport class SharedModule {\n}\n```\n\n#### 3. Use Drag-and-Drop operations with no code\n\n```js\nimport {Component} from '@angular/core';\n\n@Component({\n    selector: 'simple-dnd',\n    template: `\n\u003ch4\u003eSimple Drag-and-Drop\u003c/h4\u003e\n\u003cdiv class=\"row\"\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv class=\"panel panel-success\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003eAvailable to drag\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cdiv class=\"panel panel-default\" dnd-draggable [dragEnabled]=\"true\"\u003e\n                    \u003cdiv class=\"panel-body\"\u003e\n                        \u003cdiv\u003eDrag Me\u003c/div\u003e\n                    \u003c/div\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv dnd-droppable class=\"panel panel-info\" (onDropSuccess)=\"simpleDrop=$event\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003ePlace to drop\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cdiv *ngIf=\"simpleDrop\"\u003eItem was dropped here\u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e`\n})\nexport class SimpleDndComponent {\n    simpleDrop: any = null;\n}\n```\n\n#### 4. Add handle to restrict draggable zone of component\n\n```js\nimport {Component} from '@angular/core';\n\n@Component({\n    selector: 'simple-dnd-handle',\n    template: `\n\u003ch4\u003eSimple Drag-and-Drop with handle\u003c/h4\u003e\n\u003cdiv class=\"row\"\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv class=\"panel panel-success\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003eAvailable to drag\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cdiv class=\"panel panel-default\" dnd-draggable [dragEnabled]=\"true\"\u003e\n                    \u003cdiv class=\"panel-body\"\u003e\n                        \u003cdiv\u003e\n                            \u003cspan dnd-draggable-handle\u003e=\u003c/span\u003e\u0026nbsp;\n                            Drag Handle\n                        \u003c/div\u003e\n                    \u003c/div\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv dnd-droppable class=\"panel panel-info\" (onDropSuccess)=\"simpleDrop=$event\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003ePlace to drop\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cdiv *ngIf=\"simpleDrop\"\u003eItem was dropped here\u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e`\n})\nexport class SimpleDndHandleComponent {\n    simpleDrop: any = null;\n}\n```\n\n#### 5. Restriction Drag-and-Drop operations with drop zones\nYou can use property *dropZones* (actually an array) to specify in which place you would like to drop the draggable element:\n\n```js\nimport {Component} from '@angular/core';\n\n@Component({\n    selector: 'zone-dnd',\n    template: `\n\u003ch4\u003eRestricted Drag-and-Drop with zones\u003c/h4\u003e\n\u003cdiv class=\"row\"\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv class=\"panel panel-primary\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003eAvailable to drag\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cdiv class=\"panel panel-default\" dnd-draggable [dragEnabled]=\"true\" [dropZones]=\"['zone1']\"\u003e\n                    \u003cdiv class=\"panel-body\"\u003e\n                        \u003cdiv\u003eDrag Me\u003c/div\u003e\n                        \u003cdiv\u003eZone 1 only\u003c/div\u003e\n                    \u003c/div\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n\n        \u003cdiv class=\"panel panel-success\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003eAvailable to drag\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cdiv class=\"panel panel-default\" dnd-draggable [dragEnabled]=\"true\" [dropZones]=\"['zone1', 'zone2']\"\u003e\n                    \u003cdiv class=\"panel-body\"\u003e\n                        \u003cdiv\u003eDrag Me\u003c/div\u003e\n                        \u003cdiv\u003eZone 1 \u0026 2\u003c/div\u003e\n                    \u003c/div\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv dnd-droppable class=\"panel panel-info\" [dropZones]=\"['zone1']\" (onDropSuccess)=\"restrictedDrop1=$event\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003eZone 1\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cdiv *ngIf=\"restrictedDrop1\"\u003eItem was dropped here\u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv dnd-droppable class=\"panel panel-warning\" [dropZones]=\"['zone2']\" (onDropSuccess)=\"restrictedDrop2=$event\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003eZone 2\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cdiv *ngIf=\"restrictedDrop2\"\u003eItem was dropped here\u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e`\n})\nexport class ZoneDndComponent {\n    restrictedDrop1: any = null;\n    restrictedDrop2: any = null;\n}\n```\n\n#### 6. Transfer custom data via Drag-and-Drop\nYou can transfer data from draggable to droppable component via *dragData* property of Draggable component:\n\n```js\nimport {Component} from '@angular/core';\n\n@Component({\n    selector: 'custom-data-dnd',\n    template: `\n\u003ch4\u003eTransfer custom data in Drag-and-Drop\u003c/h4\u003e\n\u003cdiv class=\"row\"\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv class=\"panel panel-success\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003eAvailable to drag\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cdiv class=\"panel panel-default\" dnd-draggable [dragEnabled]=\"true\" [dragData]=\"transferData\"\u003e\n                    \u003cdiv class=\"panel-body\"\u003e\n                        \u003cdiv\u003eDrag Me\u003c/div\u003e\n                        \u003cdiv\u003e{{transferData | json}}\u003c/div\u003e\n                    \u003c/div\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv dnd-droppable class=\"panel panel-info\" (onDropSuccess)=\"transferDataSuccess($event)\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003ePlace to drop (Items:{{receivedData.length}})\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cdiv [hidden]=\"!receivedData.length \u003e 0\" *ngFor=\"let data of receivedData\"\u003e{{data | json}}\u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e`\n})\nexport class CustomDataDndComponent {\n    transferData: Object = {id: 1, msg: 'Hello'};\n    receivedData: Array\u003cany\u003e = [];\n\n    transferDataSuccess($event: any) {\n        this.receivedData.push($event);\n    }\n}\n```\n\n#### 7. Use a custom function to determine where dropping is allowed\nFor 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.\n\nIn 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.\n\n```js\nimport { Component } from '@angular/core';\n\n@Component({\n    selector: 'custom-function-dnd',\n    template: `\n\u003ch4\u003eUse a custom function to determine where dropping is allowed\u003c/h4\u003e\n\u003cdiv class=\"row\"\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv class=\"panel panel-success\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003eAvailable to drag\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cdiv class=\"panel panel-default\" dnd-draggable [dragData]=\"6\"\u003e\n                    \u003cdiv class=\"panel-body\"\u003edragData = 6\u003c/div\u003e\n                \u003c/div\u003e\n                \u003cdiv class=\"panel panel-default\" dnd-draggable [dragData]=\"10\"\u003e\n                    \u003cdiv class=\"panel-body\"\u003edragData = 10\u003c/div\u003e\n                \u003c/div\u003e\n                \u003cdiv class=\"panel panel-default\" dnd-draggable [dragData]=\"30\"\u003e\n                    \u003cdiv class=\"panel-body\"\u003edragData = 30\u003c/div\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"col-sm-6\"\u003e\n        \u003cpre\u003eallowDropFunction(baseInteger: any): any {{ '{' }}\n  return (dragData: any) =\u003e dragData % baseInteger === 0;\n{{ '}' }}\u003c/pre\u003e\n        \u003cdiv class=\"row\"\u003e\n            \u003cdiv class=\"col-sm-6\"\u003e\n                \u003cdiv dnd-droppable class=\"panel panel-info\" [allowDrop]=\"allowDropFunction(box1Integer)\" (onDropSuccess)=\"addTobox1Items($event)\"\u003e\n                    \u003cdiv class=\"panel-heading\"\u003e\n                        Multiples of\n                        \u003cinput type=\"number\" [(ngModel)]=\"box1Integer\" style=\"width: 4em\"\u003e\n                        only\n                    \u003c/div\u003e\n                    \u003cdiv class=\"panel-body\"\u003e\n                        \u003cdiv *ngFor=\"let item of box1Items\"\u003edragData = {{item}}\u003c/div\u003e\n                    \u003c/div\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n            \u003cdiv class=\"col-sm-6\"\u003e\n                \u003cdiv dnd-droppable class=\"panel panel-warning\" [allowDrop]=\"allowDropFunction(box2Integer)\" (onDropSuccess)=\"addTobox2Items($event)\"\u003e\n                    \u003cdiv class=\"panel-heading\"\u003e\n                        Multiples of\n                        \u003cinput type=\"number\" [(ngModel)]=\"box2Integer\" style=\"width: 4em\"\u003e\n                        only\n                    \u003c/div\u003e\n                    \u003cdiv class=\"panel-body\"\u003e\n                        \u003cdiv *ngFor=\"let item of box2Items\"\u003edragData = {{item}}\u003c/div\u003e\n                    \u003c/div\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n`\n})\nexport class CustomFunctionDndComponent {\n    box1Integer: number = 3;\n    box2Integer: number = 10;\n\n    box1Items: string[] = [];\n    box2Items: string[] = [];\n\n    allowDropFunction(baseInteger: number): any {\n        return (dragData: any) =\u003e dragData % baseInteger === 0;\n    }\n\n    addTobox1Items($event: any) {\n        this.box1Items.push($event.dragData);\n    }\n\n    addTobox2Items($event: any) {\n        this.box2Items.push($event.dragData);\n    }\n}\n```\n\n#### 8. Shopping basket with Drag-and-Drop\nHere is an example of shopping backet with products adding via drag and drop operation:\n\n```js\nimport { Component } from '@angular/core';\n\n@Component({\n    selector: 'shoping-basket-dnd',\n    template: `\n\u003ch4\u003eDrag-and-Drop - Shopping basket\u003c/h4\u003e\n\u003cdiv class=\"row\"\u003e\n\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv class=\"panel panel-success\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003eAvailable products\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cdiv *ngFor=\"let product of availableProducts\" class=\"panel panel-default\"\n                    dnd-draggable [dragEnabled]=\"product.quantity\u003e0\" [dragData]=\"product\" (onDragSuccess)=\"orderedProduct($event)\" [dropZones]=\"['demo1']\"\u003e\n                    \u003cdiv class=\"panel-body\"\u003e\n                        \u003cdiv [hidden]=\"product.quantity===0\"\u003e{{product.name}} - \\${{product.cost}}\u003cbr\u003e(available: {{product.quantity}})\u003c/div\u003e\n                        \u003cdiv [hidden]=\"product.quantity\u003e0\"\u003e\u003cdel\u003e{{product.name}}\u003c/del\u003e\u003cbr\u003e(NOT available)\u003c/div\u003e\n                    \u003c/div\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv dnd-droppable (onDropSuccess)=\"addToBasket($event)\" [dropZones]=\"['demo1']\" class=\"panel panel-info\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003eShopping Basket\u003cbr\u003e(to pay: \\${{totalCost()}})\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cdiv *ngFor=\"let product of shoppingBasket\" class=\"panel panel-default\"\u003e\n                    \u003cdiv class=\"panel-body\"\u003e\n                    {{product.name}}\u003cbr\u003e(ordered: {{product.quantity}}\u003cbr\u003ecost: \\${{product.cost * product.quantity}})\n                    \u003c/div\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e`\n})\nexport class ShoppingBasketDndComponent {\n    availableProducts: Array\u003cProduct\u003e = [];\n    shoppingBasket: Array\u003cProduct\u003e = [];\n\n    constructor() {\n        this.availableProducts.push(new Product('Blue Shoes', 3, 35));\n        this.availableProducts.push(new Product('Good Jacket', 1, 90));\n        this.availableProducts.push(new Product('Red Shirt', 5, 12));\n        this.availableProducts.push(new Product('Blue Jeans', 4, 60));\n    }\n\n    orderedProduct($event: any) {\n        let orderedProduct: Product = $event.dragData;\n        orderedProduct.quantity--;\n    }\n\n    addToBasket($event: any) {\n        let newProduct: Product = $event.dragData;\n        for (let indx in this.shoppingBasket) {\n            let product: Product = this.shoppingBasket[indx];\n            if (product.name === newProduct.name) {\n                product.quantity++;\n                return;\n            }\n        }\n        this.shoppingBasket.push(new Product(newProduct.name, 1, newProduct.cost));\n        this.shoppingBasket.sort((a: Product, b: Product) =\u003e {\n            return a.name.localeCompare(b.name);\n        });\n    }\n\n    totalCost(): number {\n        let cost: number = 0;\n        for (let indx in this.shoppingBasket) {\n            let product: Product = this.shoppingBasket[indx];\n            cost += (product.cost * product.quantity);\n        }\n        return cost;\n    }\n}\n\nclass Product {\n  constructor(public name: string, public quantity: number, public cost: number) {}\n}\n```\n\n#### 9. Simple sortable with Drag-and-Drop\nHere is an example of simple sortable of favorite drinks moving in container via drag and drop operation:\n\n```js\nimport {Component} from '@angular/core';\n\n@Component({\n    selector: 'simple-sortable',\n    template: `\n\u003ch4\u003eSimple sortable\u003c/h4\u003e\n\u003cdiv class=\"row\"\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv class=\"panel panel-success\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003e\n                Favorite drinks\n            \u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cul class=\"list-group\" dnd-sortable-container [sortableData]=\"listOne\"\u003e\n                    \u003cli *ngFor=\"let item of listOne; let i = index\" class=\"list-group-item\" dnd-sortable [sortableIndex]=\"i\"\u003e{{item}}\u003c/li\u003e\n                \u003c/ul\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"col-sm-6\"\u003e\n        \u003cdiv class=\"panel panel-default\"\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                My prefences:\u003cbr/\u003e\n                \u003cspan *ngFor=\"let item of listOne; let i = index\"\u003e{{i + 1}}) {{item}}\u003cbr/\u003e\u003c/span\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e`\n})\nexport class SimpleSortableComponent {\n    listOne: Array\u003cstring\u003e = ['Coffee', 'Orange Juice', 'Red Wine', 'Unhealty drink!', 'Water'];\n}\n```\n\n\n#### 10. Simple sortable with Drag-and-Drop handle\nAdd handle to restict grip zone of sortable component.\n\n```js\nimport {Component} from '@angular/core';\n\n@Component({\n    selector: 'simple-sortable-handle',\n    template: `\n\u003ch4\u003eSimple sortable handle\u003c/h4\u003e\n\u003cdiv class=\"row\"\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv class=\"panel panel-success\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003e\n                Favorite drinks\n            \u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cul class=\"list-group\" dnd-sortable-container [sortableData]=\"listOne\"\u003e\n                    \u003cli *ngFor=\"let item of listOne; let i = index\" class=\"list-group-item\" dnd-sortable [sortableIndex]=\"i\"\u003e\n                      \u003cspan dnd-sortable-handle\u003e=\u003c/span\u003e\u0026nbsp;\n                      {{item}}\n                    \u003c/li\u003e\n                \u003c/ul\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"col-sm-6\"\u003e\n        \u003cdiv class=\"panel panel-default\"\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                My prefences:\u003cbr/\u003e\n                \u003cspan *ngFor=\"let item of listOne; let i = index\"\u003e{{i + 1}}) {{item}}\u003cbr/\u003e\u003c/span\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e`\n})\nexport class SimpleSortableHandleComponent {\n    listOne: Array\u003cstring\u003e = ['Coffee', 'Orange Juice', 'Red Wine', 'Unhealty drink!', 'Water'];\n}\n```\n\n#### 11. Simple sortable With Drop into recycle bin\nHere is an example of multi list sortable of boxers moving in container and between containers via drag and drop operation:\n\n```js\nimport {Component} from '@angular/core';\n\n@Component({\n    selector: 'recycle-multi-sortable',\n    template: `\n\u003ch4\u003eSimple sortable With Drop into recycle bin\u003c/h4\u003e\n\u003cdiv class=\"row\"\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv class=\"panel panel-success\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003e\n                Favorite drinks\n            \u003c/div\u003e\n            \u003cdiv class=\"panel-body\" dnd-sortable-container [sortableData]=\"listOne\" [dropZones]=\"['delete-dropZone']\"\u003e\n                \u003cul class=\"list-group\"\u003e\n                    \u003cli *ngFor=\"let item of listOne; let i = index\" class=\"list-group-item\"\n                    dnd-sortable [sortableIndex]=\"i\"\u003e{{item}}\u003c/li\u003e\n                \u003c/ul\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"col-sm-6\"\u003e\n        \u003cdiv class=\"panel panel-default\"\u003e\n            \u003cdiv class=\"panel-body\" dnd-sortable-container [dropZones]=\"['delete-dropZone']\" [sortableData]=\"listRecycled\"\u003e\n                Recycle bin: Drag into me to delete it\u003cbr/\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n        \u003cdiv *ngIf=\"listRecycled.length\"\u003e\n        \u003cb\u003eRecycled:\u003c/b\u003e \u003cspan\u003e{{listRecycled.toString()}} \u003c/span\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e`\n})\nexport class RecycleMultiSortableComponent {\n    listOne: Array\u003cstring\u003e = ['Coffee', 'Orange Juice', 'Red Wine', 'Unhealty drink!', 'Water'];\n    listRecycled: Array\u003cstring\u003e = [];\n}\n```\n\n#### 12. Simple sortable With Drop into something, without delete it\nHere is an example of simple sortable list of items copying in target container:\n\n```js\nimport {Component} from '@angular/core';\n\n@Component({\n    selector: 'simple-sortable-copy',\n    template: `\n\u003ch4\u003eSimple sortable With Drop into something, without delete it\u003c/h4\u003e\n\u003cdiv class=\"row\"\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv class=\"panel panel-warning\"\n            dnd-sortable-container [sortableData]=\"sourceList\" [dropZones]=\"['source-dropZone']\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003eSource List\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cul class=\"list-group\"\u003e\n                    \u003cli *ngFor=\"let source of sourceList; let x = index\" class=\"list-group-item\"\n                        dnd-sortable [sortableIndex]=\"x\" [dragEnabled]=\"true\"\n                        [dragData]=\"source\"\u003e{{source.name}}\u003c/li\u003e\n                \u003c/ul\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"col-sm-6\"\u003e\n        \u003cdiv class=\"panel panel-info\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003eTarget List\u003c/div\u003e\n            \u003cdiv class=\"panel-body\" dnd-droppable (onDropSuccess)=\"addTo($event)\" [dropZones]=\"['source-dropZone']\"\u003e\n                \u003cul class=\"list-group\"\u003e\n                    \u003cli *ngFor=\"let target of targetList\" class=\"list-group-item\"\u003e\n                        {{target.name}}\n                    \u003c/li\u003e\n                \u003c/ul\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e`\n})\nexport class SimpleSortableCopyComponent {\n\n    sourceList: Widget[] = [\n        new Widget('1'), new Widget('2'),\n        new Widget('3'), new Widget('4'),\n        new Widget('5'), new Widget('6')\n    ];\n\n    targetList: Widget[] = [];\n    addTo($event: any) {\n        this.targetList.push($event.dragData);\n    }\n}\n\nclass Widget {\n  constructor(public name: string) {}\n}\n```\n\n#### 13. Multi list sortable between containers\nHere is an example of multi list sortable of boxers moving in container and between containers via drag and drop operation:\n\n```js\nimport {Component} from '@angular/core';\n\n@Component({\n    selector: 'embedded-sortable',\n    template: `\n\u003ch4\u003eMove items between multi list sortable containers\u003c/h4\u003e\n\u003cdiv class=\"row\"\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        Drag Containers \u003cinput type=\"checkbox\" [(ngModel)]=\"dragOperation\"/\u003e\n        \u003cdiv dnd-sortable-container [sortableData]=\"containers\" [dropZones]=\"['container-dropZone']\"\u003e\n            \u003cdiv class=\"col-sm3\"\n                    *ngFor=\"let container of containers; let i = index\"\n                    dnd-sortable [sortableIndex]=\"i\" [dragEnabled]=\"dragOperation\"\u003e\n                \u003cdiv class=\"panel panel-warning\"\n                    dnd-sortable-container [sortableData]=\"container.widgets\" [dropZones]=\"['widget-dropZone']\"\u003e\n                    \u003cdiv class=\"panel-heading\"\u003e\n                        {{container.id}} - {{container.name}}\n                    \u003c/div\u003e\n                    \u003cdiv class=\"panel-body\"\u003e\n                        \u003cul class=\"list-group\"\u003e\n                            \u003cli *ngFor=\"let widget of container.widgets; let x = index\" class=\"list-group-item\"\n                                dnd-sortable [sortableIndex]=\"x\" [dragEnabled]=\"!dragOperation\"\n                                [dragData]=\"widget\"\u003e{{widget.name}}\u003c/li\u003e\n                        \u003c/ul\u003e\n                    \u003c/div\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"col-sm-6\"\u003e\n        \u003cdiv class=\"panel panel-info\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003eWidgets\u003c/div\u003e\n            \u003cdiv class=\"panel-body\" dnd-droppable (onDropSuccess)=\"addTo($event)\" [dropZones]=\"['widget-dropZone']\"\u003e\n                \u003cdiv *ngFor=\"let widget of widgets\" class=\"panel panel-default\"\u003e\n                    \u003cdiv class=\"panel-body\"\u003e\n                        {{widget.name}}\n                    \u003c/div\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e`\n})\nexport class EmbeddedSortableComponent {\n    dragOperation: boolean = false;\n\n    containers: Array\u003cContainer\u003e = [\n        new Container(1, 'Container 1', [new Widget('1'), new Widget('2')]),\n        new Container(2, 'Container 2', [new Widget('3'), new Widget('4')]),\n        new Container(3, 'Container 3', [new Widget('5'), new Widget('6')])\n    ];\n\n    widgets: Array\u003cWidget\u003e = [];\n    addTo($event: any) {\n        if ($event) {\n            this.widgets.push($event.dragData);\n        }\n    }\n}\n\nclass Container {\n  constructor(public id: number, public name: string, public widgets: Array\u003cWidget\u003e) {}\n}\n\nclass Widget {\n  constructor(public name: string) {}\n}\n```\n\n#### 14. Simple FormArray sortable with Drag-and-Drop\nHere is an example of simple sortable of favorite drinks moving in container via drag and drop operation but using FormArray instead of Array:\n\n```js\nimport {Component} from '@angular/core';\nimport {FormArray, FormControl} from '@angular/forms';\n\n@Component({\n    selector: 'simple-formarray-sortable',\n    template: `\n\u003ch4\u003eSimple FormArray sortable\u003c/h4\u003e\n\u003cdiv class=\"row\"\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv class=\"panel panel-success\"\u003e\n            \u003cdiv class=\"panel-heading\"\u003e\n                Favorite drinks\n            \u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cul class=\"list-group\" dnd-sortable-container [sortableData]=\"listOne\"\u003e\n                    \u003cli *ngFor=\"let item of listOne.controls; let i = index\" class=\"list-group-item\" dnd-sortable [sortableIndex]=\"i\"\u003e\u003cinput type=\"text\" [formControl]=\"item\"\u003e\u003c/li\u003e\n                \u003c/ul\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"col-sm-6\"\u003e\n        \u003cdiv class=\"panel panel-default\"\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                My prefences:\u003cbr/\u003e\n                \u003cspan *ngFor=\"let item of listOne.controls; let i = index\"\u003e{{i + 1}}) {{item.value}}\u003cbr/\u003e\u003c/span\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e`\n})\nexport class SimpleFormArraySortableComponent {\n    listOne: FormArray = new FormArray([\n      new FormControl('Coffee'),\n      new FormControl('Orange Juice'),\n      new FormControl('Red Wine'),\n      new FormControl('Unhealty drink!'),\n      new FormControl('Water')\n    ]);\n}\n```\n\n## How to pass multiple data in dragData while dragging ?\n\n1) As an array: \n\n``` html\n[dragData]=\"[aComponent,'component-in-bar']\"\n```\n\n``` javascript\nloadComponent($event){\n    console.log($event.dragData[0]); // aComponent \n    console.log($event.dragData[1]); // 'component-in-bar' OR 'component-in-designer' \n}\n```\n\n2) As an object: \n\n``` html\n[dragData]=\"{component: aComponent, location: 'component-in-bar'}\"\n```\n\n``` javascript\nloadComponent($event){\n    console.log($event.dragData.component); // aComponent \n    console.log($event.dragData.location); // 'component-in-bar' OR 'component-in-designer' \n}\n```\n\n# Retreiving files in a drop zone\n\nSince it is possible to drag and drop one or more files to a drop zone, you need to handle the incoming files.\n\n```js\nimport {Component} from '@angular/core';\nimport {Http, Headers} from '@angular/http';\nimport {DND_PROVIDERS, DND_DIRECTIVES} from 'ng2-dnd/ng2-dnd';\nimport {bootstrap} from '@angular/platform-browser-dynamic';\n\nbootstrap(AppComponent, [\n    DND_PROVIDERS // It is required to have 1 unique instance of your service\n]);\n\n@Component({\n    selector: 'app',\n    directives: [DND_DIRECTIVES],\n    template: `\n\u003ch4\u003eSimple Drag-and-Drop\u003c/h4\u003e\n\u003cdiv class=\"row\"\u003e\n   \n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cdiv dnd-droppable class=\"panel panel-info\"\n            (onDropSuccess)=\"transferDataSuccess($event)\"\u003e\u003e\n            \u003cdiv class=\"panel-heading\"\u003ePlace to drop\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n`\n})\nexport class AppComponent {\n\n  constructor(private _http: Http) { }\n\n   /**\n   * The $event is a structure:\n   * {\n   *   dragData: any,\n   *   mouseEvent: MouseEvent\n   * }\n   */\n  transferDataSuccess($event) {\n    // let attachmentUploadUrl = 'assets/data/offerspec/offerspec.json';\n    // loading the FileList from the dataTransfer\n    let dataTransfer: DataTransfer = $event.mouseEvent.dataTransfer;\n    if (dataTransfer \u0026\u0026 dataTransfer.files) {\n      \n      // needed to support posting binaries and usual form values\n      let headers = new Headers();\n      headers.append('Content-Type', 'multipart/form-data');\n\n      let files: FileList = dataTransfer.files;\n  \n      // uploading the files one by one asynchrounusly\n      for (let i = 0; i \u003c files.length; i++) {\n        let file: File = files[i];\n  \n        // just for debugging\n        console.log('Name: ' + file.name + '\\n Type: ' + file.type + '\\n Size: ' + file.size + '\\n Date: ' + file.lastModifiedDate);\n  \n        // collecting the data to post\n        var data = new FormData();\n        data.append('file', file);\n        data.append('fileName', file.name);\n        data.append('fileSize', file.size);\n        data.append('fileType', file.type);\n        data.append('fileLastMod', file.lastModifiedDate);\n  \n        // posting the data\n        this._http\n          .post(attachmentUploadUrl, data, {\n            headers: headers\n          })\n          .toPromise()\n          .catch(reason =\u003e {\n            console.log(JSON.stringify(reason));\n          });\n      }\n    }\n  }\n}\n\n# Credits\n- [Francesco Cina](https://github.com/ufoscout)\n- [Valerii Kuznetsov](https://github.com/solival)\n- [Shane Oborn](https://github.com/obosha)\n- [Juergen Gutsch](https://github.com/JuergenGutsch)\n- [Damjan Cilenšek](https://github.com/loudandwicked)\n\n# License\n [MIT](/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakserg%2Fng2-dnd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakserg%2Fng2-dnd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakserg%2Fng2-dnd/lists"}