NgxDragDrop
Demo
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
- custom CSS classes
- touch support by using a polyfill
- AOT compatible
Port of angular-drag-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
<div [dndDraggable]="draggable.data"
[dndEffectAllowed]="draggable.effectAllowed"
[dndDisableIf]="draggable.disable"
(dndStart)="onDragStart($event)"
(dndCopied)="onDraggableCopied($event)"
(dndLinked)="onDraggableLinked($event)"
(dndMoved)="onDraggableMoved($event)"
(dndCanceled)="onDragCanceled($event)"
(dndEnd)="onDragEnd($event)">
<div *ngIf="draggable.handle"
dndHandle>HANDLE
</div>
draggable ({{draggable.effectAllowed}}) <span [hidden]="!draggable.disable">DISABLED</span>
<div dndDragImageRef>DRAG_IMAGE</div>
</div>
<section dndDropzone
(dndDragover)="onDragover($event)"
(dndDrop)="onDrop($event)">
dropzone
<div style="border: 1px orangered solid; border-radius: 5px; padding: 15px;"
dndPlaceholderRef>
placeholder
</div>
</section>
app.component
import { Component } from '@angular/core';
import { DndDropEvent } from 'ngx-drag-drop';
@Component()
export class AppComponent {
draggable = {
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
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
export type DropEffect = "move" | "copy" | "link" | "none";
export type EffectAllowed = DropEffect | "copyMove" | "copyLink" | "linkMove" | "all";
export type DndDragImageOffsetFunction = ( event:DragEvent, dragImage:Element ) => { x:number, y:number };
@Directive( {
selector: "[dndDraggable]"
} )
export declare class DndDraggableDirective {
dndDraggable: any;
dndEffectAllowed: EffectAllowed;
dndType?: string;
dndDisableIf: boolean;
dndDraggingClass: string = "dndDragging";
dndDraggingSourceClass: string = "dndDraggingSource";
dndDraggableDisabledClass = "dndDraggableDisabled";
dndDragImageOffsetFunction:DndDragImageOffsetFunction = calculateDragImageOffset;
readonly dndStart: EventEmitter<DragEvent>;
readonly dndEnd: EventEmitter<DragEvent>;
readonly dndMoved: EventEmitter<DragEvent>;
readonly dndCopied: EventEmitter<DragEvent>;
readonly dndLinked: EventEmitter<DragEvent>;
readonly dndCanceled: EventEmitter<DragEvent>;
}
export interface DndDropEvent {
event: DragEvent;
dropEffect: DropEffect;
isExternal:boolean;
data?: any;
index?: number;
}
@Directive( {
selector: "[dndDropzone]"
} )
export declare class DndDropzoneDirective {
dndDropzone?: string[];
dndEffectAllowed: EffectAllowed;
dndDisableIf: boolean;
dndAllowExternal: boolean;
dndHorizontal: boolean;
dndDragoverClass: string = "dndDragover";
dndDropzoneDisabledClass = "dndDropzoneDisabled";
readonly dndDragover: EventEmitter<DragEvent>;
readonly dndDrop: EventEmitter<DndDropEvent>;
}
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.
Maintenance
This project was generated with Angular CLI.
For the library build it uses ng-packagr.
Edit Library
- edit lib code
- run
npm start
(currently needs to be re-run on every lib code change)
Release Library
- assure correct version is set in
package.json
- build library with
npm run build:lib
- publish library with
npm run publish:stable
(use npm run publish:next
for pre-releases)
Release Docs
- build docs site with
npm run build:docs
- commit and push changes in
docs
to master