Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/reppners/ngx-drag-drop

Angular directives using the native HTML Drag And Drop API
https://github.com/reppners/ngx-drag-drop

Last synced: 3 months ago
JSON representation

Angular directives using the native HTML Drag And Drop API

Awesome Lists containing this project

README

        

[![npm](https://img.shields.io/npm/v/ngx-drag-drop.svg)](https://www.npmjs.com/package/ngx-drag-drop)
[![npm (next)](https://img.shields.io/npm/v/ngx-drag-drop/next.svg)](https://www.npmjs.com/package/ngx-drag-drop)
[![NpmLicense](https://img.shields.io/npm/l/ngx-drag-drop.svg)](https://www.npmjs.com/package/ngx-drag-drop)
[![GitHub issues](https://img.shields.io/github/issues/reppners/ngx-drag-drop.svg)](https://github.com/reppners/ngx-drag-drop/issues)
[![Twitter](https://img.shields.io/twitter/url/https/github.com/reppners/ngx-drag-drop.svg?style=social)](https://twitter.com/intent/tweet?text=Angular%20drag%20and%20drop%20with%20ease:&url=https://github.com/reppners/ngx-drag-drop)

# NgxDragDrop

[_Demo_](https://reppners.github.io/ngx-drag-drop/) / [_StackBlitz Issue Template_](https://stackblitz.com/edit/ngx-drag-drop-issue-template)

```sh
npm install ngx-drag-drop --save
```

**Angular directives for declarative drag and drop using the HTML5 Drag-And-Drop API**

- sortable lists by using placeholder element (vertical and horizontal)
- nestable
- dropzones optionally support external/native draggables (img, txt, file)
- conditional drag/drop
- typed drag/drop
- utilize [EffectAllowed](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/effectAllowed)
- custom CSS classes
- touch support by using a [polyfill](#touch-support)
- [AOT](https://angular.io/guide/aot-compiler) compatible

Port of [angular-drag-drop-lists](https://github.com/marceljuenemann/angular-drag-and-drop-lists) but without the lists :wink:

This has `dropzones` though :+1:
The idea is that the directive does not handle lists internally so the `dndDropzone` can be general purpose.

## Usage

`app.component.html`

```HTML


HANDLE

draggable ({{draggable.effectAllowed}}) DISABLED


DRAG_IMAGE

dropzone




placeholder

```

`app.component`

```JS
import { Component } from '@angular/core';

import { DndDropEvent } from 'ngx-drag-drop';

@Component()
export class AppComponent {

draggable = {
// note that data is handled with JSON.stringify/JSON.parse
// only set simple data or POJO's as methods will be lost
data: "myDragData",
effectAllowed: "all",
disable: false,
handle: false
};

onDragStart(event:DragEvent) {

console.log("drag started", JSON.stringify(event, null, 2));
}

onDragEnd(event:DragEvent) {

console.log("drag ended", JSON.stringify(event, null, 2));
}

onDraggableCopied(event:DragEvent) {

console.log("draggable copied", JSON.stringify(event, null, 2));
}

onDraggableLinked(event:DragEvent) {

console.log("draggable linked", JSON.stringify(event, null, 2));
}

onDraggableMoved(event:DragEvent) {

console.log("draggable moved", JSON.stringify(event, null, 2));
}

onDragCanceled(event:DragEvent) {

console.log("drag cancelled", JSON.stringify(event, null, 2));
}

onDragover(event:DragEvent) {

console.log("dragover", JSON.stringify(event, null, 2));
}

onDrop(event:DndDropEvent) {

console.log("dropped", JSON.stringify(event, null, 2));
}
}
```

`app.module`

```JS
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { DndModule } from 'ngx-drag-drop';

import { AppComponent } from './app.component';

@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
DndModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
}
```

## API

```TS
// https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/dropEffect
export type DropEffect = "move" | "copy" | "link" | "none";

// https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/effectAllowed
export type EffectAllowed = DropEffect | "copyMove" | "copyLink" | "linkMove" | "all";
```

```TS
export type DndDragImageOffsetFunction = ( event:DragEvent, dragImage:Element ) => { x:number, y:number };

@Directive( {
selector: "[dndDraggable]"
} )
export declare class DndDraggableDirective {

// the data attached to the drag
dndDraggable: any;

// the allowed drop effect
dndEffectAllowed: EffectAllowed;

// optionally set the type of dragged data to restrict dropping on compatible dropzones
dndType?: string;

// conditionally disable the draggability
dndDisableIf: boolean;
dndDisableDragIf: boolean;

// set a custom class that is applied while dragging
dndDraggingClass: string = "dndDragging";

// set a custom class that is applied to only the src element while dragging
dndDraggingSourceClass: string = "dndDraggingSource";

// set the class that is applied when draggable is disabled by [dndDisableIf]
dndDraggableDisabledClass = "dndDraggableDisabled";

// enables to set a function for calculating custom dragimage offset
dndDragImageOffsetFunction:DndDragImageOffsetFunction = calculateDragImageOffset;

// emits on drag start
readonly dndStart: EventEmitter;

// emits on drag
readonly dndDrag: EventEmitter;

// emits on drag end
readonly dndEnd: EventEmitter;

// emits when the dragged item has been dropped with effect "move"
readonly dndMoved: EventEmitter;

// emits when the dragged item has been dropped with effect "copy"
readonly dndCopied: EventEmitter;

// emits when the dragged item has been dropped with effect "link"
readonly dndLinked: EventEmitter;

// emits when the drag is canceled
readonly dndCanceled: EventEmitter;
}
```

```TS
export interface DndDropEvent {

// the original drag event
event: DragEvent;

// the actual drop effect
dropEffect: DropEffect;

// true if the drag did not origin from a [dndDraggable]
isExternal:boolean;

// the data set on the [dndDraggable] that started the drag
// for external drags use the event property which contains the original drop event as this will be undefined
data?: any;

// the index where the draggable was dropped in a dropzone
// set only when using a placeholder
index?: number;

// if the dndType input on dndDraggable was set
// it will be transported here
type?: any;
}

@Directive( {
selector: "[dndDropzone]"
} )
export declare class DndDropzoneDirective {

// optionally restrict the allowed types
dndDropzone?: string[];

// set the allowed drop effect
dndEffectAllowed: EffectAllowed;

// conditionally disable the dropzone
dndDisableIf: boolean;
dndDisableDropIf: boolean;

// if draggables that are not [dndDraggable] are allowed to be dropped
// set to true if dragged text, images or files should be handled
dndAllowExternal: boolean;

// if its a horizontal list this influences how the placeholder position
// is calculated
dndHorizontal: boolean;

// set the class applied to the dropzone
// when a draggable is dragged over it
dndDragoverClass: string = "dndDragover";

// set the class applied to the dropzone
// when the dropzone is disabled by [dndDisableIf]
dndDropzoneDisabledClass = "dndDropzoneDisabled";

// emits when a draggable is dragged over the dropzone
readonly dndDragover: EventEmitter;

// emits on successful drop
readonly dndDrop: EventEmitter;
}
```

## Touch support

Install the `mobile-drag-drop` module available on npm.

Add the following lines to your js code

```JS
import { polyfill } from 'mobile-drag-drop';
// optional import of scroll behaviour
import { scrollBehaviourDragImageTranslateOverride } from "mobile-drag-drop/scroll-behaviour";

polyfill( {
// use this to make use of the scroll behaviour
dragImageTranslateOverride: scrollBehaviourDragImageTranslateOverride
} );

// workaround to make scroll prevent work in iOS Safari >= 10
try {
window.addEventListener( "touchmove", function() { }, { passive: false } );
}
catch(e){}
```

For more info on the polyfill check it out on GitHub
https://github.com/timruffles/mobile-drag-drop

## Known issues

### Firefox

- Beware that Firefox does not support dragging on `` elements.
- `` and `` won't work.
- See https://bugzilla.mozilla.org/show_bug.cgi?id=568313

## Why?

HTML Drag-And-Drop API implementations are not behaving the same way across browsers.

The directives contained in this module enable declarative drag and drop that "just works" across browsers in a consistent way.

Credits go to the author and contributors of [angular-drag-drop-lists](https://github.com/marceljuenemann/angular-drag-and-drop-lists).

## Maintenance

This project was generated with [Angular CLI](https://github.com/angular/angular-cli).

See https://angular.io/guide/creating-libraries

#### Edit Library

- run `npm run watch:lib` for hacking on library

#### Release Library

- assure correct version is set in `projects/dnd/package.json`
- build library with `npm run build:lib`
- publish library with `npm run publish:stable` (use `npm run publish:next` for pre-releases)

#### Edit Docs

- initially and on lib changes run `npm run build:lib` to current version of lib available to the demo
- run `npm run start:docs`

#### Release Docs

- build docs site with `npm run build:docs`
- commit and push changes in `docs` to `master`

---


Made with :heart: &

jetbrains

& :coffee: