{"id":13481051,"url":"https://github.com/ObaidUrRehman/ng-drag-drop","last_synced_at":"2025-03-27T11:31:38.057Z","repository":{"id":12434849,"uuid":"71356113","full_name":"ObaidUrRehman/ng-drag-drop","owner":"ObaidUrRehman","description":"Drag \u0026 Drop for Angular - based on HTML5 with no external dependencies. :tada:","archived":false,"fork":false,"pushed_at":"2022-07-07T03:42:12.000Z","size":1684,"stargazers_count":240,"open_issues_count":75,"forks_count":122,"subscribers_count":18,"default_branch":"master","last_synced_at":"2024-04-15T02:05:00.845Z","etag":null,"topics":["angular","angular-components","angular2","angular4","angular5","drag-drop","draggable","droppable"],"latest_commit_sha":null,"homepage":"","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/ObaidUrRehman.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-10-19T12:44:39.000Z","updated_at":"2024-04-01T21:17:29.000Z","dependencies_parsed_at":"2022-08-07T06:17:00.301Z","dependency_job_id":null,"html_url":"https://github.com/ObaidUrRehman/ng-drag-drop","commit_stats":null,"previous_names":["obaidurrehman/ng2-drag-drop"],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ObaidUrRehman%2Fng-drag-drop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ObaidUrRehman%2Fng-drag-drop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ObaidUrRehman%2Fng-drag-drop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ObaidUrRehman%2Fng-drag-drop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ObaidUrRehman","download_url":"https://codeload.github.com/ObaidUrRehman/ng-drag-drop/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":220284335,"owners_count":16623741,"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","angular-components","angular2","angular4","angular5","drag-drop","draggable","droppable"],"created_at":"2024-07-31T17:00:48.127Z","updated_at":"2024-10-30T14:31:15.231Z","avatar_url":"https://github.com/ObaidUrRehman.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 Drag \u0026 Drop\n\n## :warning: Discontinuation Notice\nAlmost 2 years ago I created this component to support HTML native drag drop in Angular. At that time there were a handful of libraries \u0026 they did not had the features I wanted. Today, with the release of Angular 7 \u0026 the CDK's drag drop component we finally have a much better alternative for this component.\nPlease use [Angular CDK's drag drop](https://material.angular.io/cdk/drag-drop/overview).\n\n\n[![Join the chat at https://join.slack.com/t/ng-drag-drop/shared_invite/MjM5ODY5MDUyODY1LTE1MDUyOTk0OTMtNjFhZmJiOTE2Zg](https://img.shields.io/badge/chat-on_slack-ff69b4.svg?style=flat-square)](https://join.slack.com/t/ng-drag-drop/shared_invite/MjM5ODY5MDUyODY1LTE1MDUyOTk0OTMtNjFhZmJiOTE2Zg)\n[![npm version](https://img.shields.io/npm/v/ng-drag-drop.svg?style=flat-square)](https://www.npmjs.com/package/ng-drag-drop) \n[![npm downloads](https://img.shields.io/npm/dm/ng-drag-drop.svg?style=flat-square)](https://www.npmjs.com/package/ng-drag-drop) \n[![Build Status](https://img.shields.io/travis/ObaidUrRehman/ng-drag-drop.svg?style=flat-square)](https://travis-ci.org/ObaidUrRehman/ng-drag-drop) \n[![Codacy Badge](https://img.shields.io/codacy/grade/98ef19fdf92448d699bd93badd16e2f5.svg?style=flat-square)](https://www.codacy.com/app/orehman/ng-drag-drop?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=ObaidUrRehman/ng-drag-drop\u0026amp;utm_campaign=Badge_Grade)\n\nDrag \u0026 Drop for [Angular](http://angular.io), based on HTML5 with no external dependencies. Provides `draggable` \u0026 `droppable` directives. Features:\n* Transfer data from `draggable` to `droppable`.\n* Restrict drop based on drag-drop scopes.\n* Restrict drag to happen from either drag handles or the entire element.\n* Add custom drag Helper Image\n* Ability to add custom visual cue styles.\n\n![Demo](https://raw.githubusercontent.com/ObaidUrRehman/ng-drag-drop/master/drag-drop.gif)\n\n# Content\n\n1. [Demo](#demo)\n2. [Installation](#installation)\n3. [Usage](#usage)\n4. [Limitations](#limitations)\n5. [Development](#development)\n6. [API Doc](#api-doc)\n7. [Tips and Tricks](#tips-and-tricks)\n\n# Demo\n\nCheck out the [Plunker demo](http://plnkr.co/edit/2bjGgzWnbFrciEiCKLew?p=preview).\n\n\nThe [demo folder](https://github.com/ObaidUrRehman/ng-drag-drop/tree/master/demo) of the repository contains the same demo as Plunkr that uses SystemJS. To run that demo do an `npm install` in that folder followed by `npm start` to serve the demo app.\n\n# Installation\n```js\nnpm install ng-drag-drop --save\n```\n\n# Usage\n\n### Import default styles\nImport `style.css` into your index.html. It has a set of default styles that will be applied upon drag operations. This is totally optional and you can modify the styles as per your need. See the [Adding visual cues](#adding-visual-cues) Section.\n\n```html\n\u003clink rel=\"stylesheet\" href=\"node_modules/ng-drag-drop/style.css\"\u003e\n```\n\n### Update SystemJS config\nIf you use SystemJS as your module loader then you will need to update the config to load the `ng-drag-drop` module.\n```js\nSystem.config({\n    map: {\n        'ng-drag-drop': 'node_modules/ng-drag-drop'\n    },\n    packages: {\n        'ng-drag-drop':  { main: 'index.js',  defaultExtension: 'js' },\n    }\n});\n```\n### Import `NgDragDropModule`\n\nYou need to import the `NgDragDropModule` in the module of your app where you want to use it.\n\n```js\nimport { NgModule } from '@angular/core';\nimport { BrowserModule } from '@angular/platform-browser';\nimport { DemoComponent } from \"./components/demo-component\";\nimport { NgDragDropModule } from 'ng-drag-drop';\n\n\n@NgModule({\n  imports: [\n      BrowserModule, \n      NgDragDropModule.forRoot()\n  ],\n  declarations: [DemoComponent],\n  bootstrap: [DemoComponent]\n})\nexport class AppModule {}\n```\n\n### Use the `draggable` \u0026 `droppable` directives\nPlace the `draggable` directive on an element that you want to be draggable. The following example makes the\n List item draggable:\n\n```html\n\u003cul\u003e\n  \u003cli draggable\u003eCoffee\u003c/li\u003e\n  \u003cli draggable\u003eTea\u003c/li\u003e\n  \u003cli draggable\u003eMilk\u003c/li\u003e\n\u003c/ul\u003e               \n```\n\nSimilarly use the `droppable` directive on an element where you want to drop `draggable`:\n \n ```html\n \u003cdiv droppable\u003e\n   \u003cp\u003eDrop items here\u003c/p\u003e\n \u003c/div\u003e               \n ```\n\n### Restrict Drop based on Scopes\nYou can use the `dragScope` \u0026 `dropScope` property on `draggable` and `droppable` respectively to restrict user from dropping a `draggable` element into a `droppable`.\n The Scope properties can be string, an Array of string (to indicate multiple scope) or a function. The scopes must match in both to indicate compatible drag-drop zones.\n \n In the following example, only the `draggable` with the `drink` dropScope can be dropped on the first `droppable` and both `drink` and `meal` can be dropped in the second one.\n \n```html\n\u003cul\u003e\n  \u003cli draggable [dragScope]=\"'drink'\"\u003eCoffee\u003c/li\u003e\n  \u003cli draggable [dragScope]=\"'drink'\"\u003eTea\u003c/li\u003e\n  \u003cli draggable [dragScope]=\"'meal'\"\u003eBiryani\u003c/li\u003e\n  \u003cli draggable [dragScope]=\"'meal'\"\u003eKebab\u003c/li\u003e\n  ...\n\u003c/ul\u003e               \n```\n\n```html\n\u003cdiv droppable [dropScope]=\"'drink'\" [dragOverClass]=\"'drag-target-border'\"\u003e\n  \u003cp\u003eOnly Drinks can be dropped in the above container\u003c/p\u003e\n\u003c/div\u003e               \n\n\u003cdiv droppable [dropScope]=\"['drink', 'meal']\" [dragOverClass]=\"'drag-target-border'\"\u003e\n  \u003cp\u003eBoth Meal and Drinks can be dropped in the above container\u003c/p\u003e\n\u003c/div\u003e               \n```\n### Drop Scope as Functions\n\nThe `DropScope` of the `droppable` can be a function whose return value will determine if drop is allowed.\nThis can be useful to implement complex logic that is otherwise not possible with string or array of string.\n\n```html\n\u003cdiv droppable [dropScope]=\"dropAllowed\" [dragOverClass]=\"'drag-target-border'\"\u003e\n  \u003cp\u003eOnly those items are droppable for which the `isDropAllowed()` function returns true\u003c/p\u003e\n\u003c/div\u003e\n```\nHere is how the function is defined in the component:\n```js\nexport class MyComponent {\n  val = 500;\n  isDropAllowed = (dragData: any) =\u003e {\n    return dragData \u003e this.val;\n  }\n}\n```\nNotice how the function is defined as an [Arrow Function](https://www.typescriptlang.org/docs/handbook/functions.html). You need to do this so the\nlexical scope of `this` is preserved. You also get the `dragData` in the parameter so you can compare it with whatever you want.\n\nIf `DropScope` is a function, it can also return an `Observable`, which needs to later resolve to `true` or `false`. This can help in cases when\nyou need to check asynchronously (eg: via http) whether the drop is allowed.\n\n```js\nexport class MyComponent {\n  val = 500;\n  isDropAllowed = (dragData: any) =\u003e {\n    // Resolves to true or false after 1 second\n    return Observable.of(dragData \u003e this.val).delay(1000);\n  }\n}\n```\n  \n### Transfer Data via Drag Drop\nYou can transfer data from the `draggable` to the `droppable` via the `dragData` property on the `draggable` directive. \n The data will be received in the `(onDrop)` event of the `droppable`:\n\n```js\nimport {Component} from '@angular/core';\n\n@Component({\n    selector: 'app',\n    template: `\n\u003ch3\u003eTransfer Data via Drag Drop\u003c/h3\u003e\n\u003cdiv class=\"row\"\u003e\n    \u003cdiv class=\"col-sm-3\"\u003e\n        \u003cul class=\"list-group\"\u003e\n            \u003cli draggable *ngFor=\"let item of items\" [dragData]=\"item\" class=\"list-group-item\"\u003e{{item.name}}\u003c/li\u003e\n        \u003c/ul\u003e\n    \u003c/div\u003e\n    \n    \u003cdiv class=\"col-sm-3\"\u003e\n    \u003cdiv class=\"panel panel-default\" droppable (onDrop)=\"onItemDrop($event)\"\u003e\n        \u003cdiv class=\"panel-heading\"\u003eDrop Items here\u003c/div\u003e\n            \u003cdiv class=\"panel-body\"\u003e\n                \u003cli *ngFor=\"let item of droppedItems\" class=\"list-group-item\"\u003e{{item.name}}\u003c/li\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n`\n})\nexport class AppComponent {\n    items = [\n            {name: \"Apple\", type: \"fruit\"},\n            {name: \"Carrot\", type: \"vegetable\"},\n            {name: \"Orange\", type: \"fruit\"}];\n            \n    onItemDrop(e: any) {\n        // Get the dropped data here\n        this.droppedItems.push(e.dragData);\n    }\n    constructor() { }\n}             \n```\n\n### Drag Handle\nDrag Handle can be defined for a `draggable` item which will restrict drag of the element unless the item is dragged from the specified element.\n The handle should be a valid selector string. Example: \n```html\n\u003cli draggable [dragHandle]=\"'.drag-handle'\"\u003e\n   Not Draggable by list item but by the handle only.    \n   \u003cdiv class=\"pull-right\"\u003e\u003ci class=\"drag-handle fa fa-bars fa-lg\" aria-hidden=\"true\"\u003e\u003c/i\u003e\u003c/div\u003e \n\u003c/li\u003e               \n```\n\n### Drag Helper Image\nBy default when an element is dragged, a translucent image is generated from the drag target. This image is generated automatically and varies with browser. A custom image can be used if desired. Pass the url of the image to `[dragImage]` on the `draggable` directive.\n\n```html\n\u003cli draggable [dragImage] = \"'../../images/drag-helper.png'\" \u003e\n   Not Draggable by list item but by the handle only.    \n   \u003cdiv class=\"pull-right\"\u003e\u003ci class=\"drag-handle fa fa-bars fa-lg\" aria-hidden=\"true\"\u003e\u003c/i\u003e\u003c/div\u003e \n\u003c/li\u003e               \n```\n__Compatibility:__ This only works on Chrome \u0026 Firefox. Not supported on Edge.\n\n### Adding visual cues\n![Demo](https://raw.githubusercontent.com/ObaidUrRehman/ng-drag-drop/master/ui-cue.gif)\n\nBoth the `draggable` \u0026 `droppable` directives take a bunch of inputs that let you apply class on various events. You can find the list below. Another thing you can do is clone the `style.css` that comes with this package and customize it as per your requirement.\n\n__Draggable Directive__\n1. [dragHandleClass](#draggable-directive)\n2. [dragClass](#draggable-directive)\n3. [dragTransitClass](#draggable-directive)\n\n__Droppable Directive__\n1. [dragOverClass](#droppable-directive)\n2. [dragHintClass](#droppable-directive)\n \n Here is how a custom class is applied to a draggable element:\n ```html\n \u003cdiv draggable [dragHandleClass]=\"'my-draggable'\"\u003e\n   \u003cp\u003eDrop items here\u003c/p\u003e\n \u003c/div\u003e               \n ```\n # Limitations\nThis library uses [Native Html5 drag \u0026 drop API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API) to accomplish what it does. Because of this, certain aspects are not customizable and some UI behaviour is browser specific. \n\nSo if you were to see the demo under Edge or Chrome/Firefox you'll see that these browsers show a different behaviour when an Item is being dragged. Simlarly Edge does not let you set a custom dragImage while others do. Another major issues is that we can't control the opacity of the ghost element of item being dragged.\n\nTo overcome these issues we'll need to implement our own drag drop functionality instead of relying on the Native Html API which at this point in time, is beyond the scope of this component. Libraries like [Dragula](http://valor-software.com/ng2-dragula/), [JQuery Draggable](https://jqueryui.com/draggable/), [Interact.js](http://interactjs.io/) to name a few, can provide you with alternatives.\n\n## Touch Support\nHTML5 Drag drop is not touch supported but you can use the [DragDropTouch](https://github.com/Bernardo-Castilho/dragdroptouch) Polyfill.\n\n# Development\nTo start the dev flow on your system, follow these steps:\n\n1. `npm install` on the root of this repo.\n2. `npm install` in the demo folder. This is where the demo app resides. Sort of a test \u0026 play yard for ng-drag-drop package.\n3. Next you need to sym-link your package with the demo folder so your changes to the package are reflected in the demo app. Please remember the demo and the package are seperate apps \u0026 the demo app does not get published to npm. To link run `npm link` on the root of the repo followed by `npm link ng-drag-drop` in demo folder. You can read more about `npm link` [here](https://docs.npmjs.com/cli/link).\n4. Finally run `npm run dev` at the root. This will open up the demo app in browser.\n5. Now you can make changes to the actual component or the demo app and debug. Please note that changing the code of demo app will autoreload the browser but you'll need to manually refresh the page if you change the component code.\n\n__Note:__ The steps are a bit involved at this time and will be simplified to an npm script in later releases.\n\n# API Doc\n### Draggable directive\n\n### Attributes\n\n| Name   | Type      |Default Value |Description |\n|:-------|:----------|:-------------|:-----------|\n| `dragData`    |   `any` | `null` | The data that will be avaliable to the droppable directive on its `onDrop()` event. |\n| `dragScope`   |    `string | Array\u003cstring\u003e` | `'default'`   |  Defines compatible drag drop pairs. Values must match with `droppable.dropScope`. |\n| `dragClass` (previously `dragOverClass`) | `string` | `'drag-border'` | CSS class applied on the draggable that is applied when the item is being dragged. |\n| `dragTransitClass` | `string` | `'drag-transit'` | CSS class applied on the drag helper translucent element clone. |\n| `dragHandleClass`  | `string` | `'drag-handle'` | The CSS class applied to a draggable element. If a dragHandle is defined then its applied to that handle element only. By default it is used to change the mouse over pointer. |\n| `draghandle` | `string` | `null` | The selector that defines the drag Handle. If defined drag will only be allowed if dragged from the selector element. |\n| `dragImage` | `string` | `null` | The url to image that will be used as custom drag image when the draggable is being dragged. |\n| `dragEnabled` | `boolean` | `true` | Defines if drag is enabled. `true` by default. |\n\n### Events\n\n| Name   | Parameters  |Description |\n|:-------|:------------|:-----------|\n| `onDragStart`  | e: DOM event   | Event fired when Drag is started  |\n| `onDrag`       | e: DOM event   | Event fired while the element is being dragged |\n| `onDragEnd`    | e: DOM event   | Event fired when dragged ends |\n\nFor more information on Drag DOM Events: [Drag Event](https://developer.mozilla.org/en-US/docs/Web/API/DragEvent) \n\n### Droppable directive\n\n### Attributes\n\n| Name   | Type      |Default Value |Description |\n|:-------|:----------|:-------------|:-----------|\n| `dropScope` |    `string | Array\u003cstring\u003e` | `'default'`   |   Defines compatible drag drop pairs. Values must match with `draggable.dragScope` |\n| `dragOverClass` | `string` | `'drag-over-border'` | CSS class applied on the droppable element when the item is being dragged over valid drop target. |\n| `dragHintClass` | `string` | `'drag-hint-border'` | CSS class applied on this droppable when a compatible draggable item is being dragged. This can be used to visually show allowed drop zones. |\n| `dropEnabled` | `boolean` | `true` | Defines if drop is enabled. `true` by default. |\n\n### Events\n\n| Name   | Parameters  |Description |\n|:-------|:------------|:-----------|\n| `onDragEnter`  | e: DOM event   | Event fired when Drag dragged element enters a valid drop target.  |\n| `onDragOver`       | e: DOM event   | Event fired when an element is being dragged over a valid drop target. |\n| `onDragLeave`    | e: DOM event   | Event fired when a dragged element leaves a valid drop target. |\n| `onDrop`    | e: `DropEvent`   | Event fired when an element is dropped on a valid drop target. |\n\n\n# Tips And Tricks\n### Change cursor to \"move\" or \"copy\" when Ctrl-key is pressed/released\nIn Chrome and Edge (Windows 10 - not tested in other browser/OS), when you drag an element, the cursor changes to \"move\" whether or not you press the Ctrl-key.\n\nFortunately, it's easy to change this behavior.\n\nOn the draggable element, you bind to the events \"onDragStart\", \"onDragOver\", \"onDragLeave\", and manipulate the cursor in the bound method of the component.\n\nSo, in the template :\n```html\n  \u003cdiv class=\"some-class\" draggable \n    (onDragStart)=\"onItemDragStart($event)\" (onDragOver)=\"onItemDragOver($event)\" (onDragLeave)=\"onItemDragLeave($event)\"\u003e\n    \u003c!-- some content here --\u003e\n  \u003c/div\u003e\n```\nAnd in the *.ts file :\n```js\n    onItemDragStart(event) {\n      event.dataTransfer.dropEffect = event.ctrlKey ? 'copy' : 'move';\n    }\n\n    onItemDragOver(event) {\n      event.dataTransfer.dropEffect = event.ctrlKey ? 'copy' : 'move';\n    }\n\n    onItemDragLeave(event) {\n      event.dataTransfer.dropEffect = event.ctrlKey ? 'copy' : 'move';\n    }\n```\nIn the droppable element, here's how you find if the Ctrl-key is pressed or not :\n\nIn the template :\n```html\n  \u003cdiv class=\"some-other-class\" droppable (onDrop)=\"onItemDrop($event)\"\u003e\n    \u003c!-- some content here --\u003e\n  \u003c/div\u003e\n```\nIn the component's *.ts file : \n```js\n    onItemDrop(event) {\n      const isCopy = event.nativeEvent.ctrlKey;\n      // do something with the dropped item\n    }\n```\n\n# License\n\nMIT\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FObaidUrRehman%2Fng-drag-drop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FObaidUrRehman%2Fng-drag-drop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FObaidUrRehman%2Fng-drag-drop/lists"}