diff --git a/README.md b/README.md index 7e6a32d..77ab5a3 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ The idea is that the directive does not handle lists internally so the `dndDropz ```JS import { Component } from '@angular/core'; -import { DndDropEvent } from 'ngx-drag-drop'; +import { DndDragEvent, DndDropEvent } from 'ngx-drag-drop'; @Component() export class AppComponent { @@ -93,27 +93,27 @@ export class AppComponent { console.log("drag started", JSON.stringify(event, null, 2)); } - onDragEnd(event:DragEvent) { + onDragEnd(event:DndDragEvent) { console.log("drag ended", JSON.stringify(event, null, 2)); } - onDraggableCopied(event:DragEvent) { + onDraggableCopied(event:DndDragEvent) { console.log("draggable copied", JSON.stringify(event, null, 2)); } - onDraggableLinked(event:DragEvent) { + onDraggableLinked(event:DndDragEvent) { console.log("draggable linked", JSON.stringify(event, null, 2)); } - onDraggableMoved(event:DragEvent) { + onDraggableMoved(event:DndDragEvent) { console.log("draggable moved", JSON.stringify(event, null, 2)); } - onDragCanceled(event:DragEvent) { + onDragCanceled(event:DndDragEvent) { console.log("drag cancelled", JSON.stringify(event, null, 2)); } @@ -168,6 +168,13 @@ export type EffectAllowed = DropEffect | "copyMove" | "copyLink" | "linkMove" | ```TS export type DndDragImageOffsetFunction = ( event:DragEvent, dragImage:Element ) => { x:number, y:number }; +export interface DndDragEvent extends DragEvent { + + // the initial index of the item being dragged + // set only when the dndDraggable has dndIndex set + initialIndex?: number; +} + @Directive( { selector: "[dndDraggable]" } ) @@ -182,6 +189,9 @@ export declare class DndDraggableDirective { // optionally set the type of dragged data to restrict dropping on compatible dropzones dndType?: string; + // optionally set the index of the item being dragged, this is useful when dragging primitives + dndIndex?: number; + // conditionally disable the draggability dndDisableIf: boolean; diff --git a/demo/app/typed/typed.component.html b/demo/app/typed/typed.component.html index d566256..e8aa1a8 100644 --- a/demo/app/typed/typed.component.html +++ b/demo/app/typed/typed.component.html @@ -14,11 +14,12 @@ class="dndPlaceholder"> - + (dndMoved)="onDragged($event.initialIndex, fruits)">

{{fruit}}

@@ -40,11 +41,12 @@

{{fruit}}

class="dndPlaceholder"> - + (dndMoved)="onDragged($event.initialIndex, apples)">

{{apple}}

@@ -65,11 +67,12 @@

{{apple}}

class="dndPlaceholder"> - + (dndMoved)="onDragged($event.initialIndex, bananas)">

{{banana}}

diff --git a/demo/app/typed/typed.component.ts b/demo/app/typed/typed.component.ts index 6756fc3..09ff5e0 100644 --- a/demo/app/typed/typed.component.ts +++ b/demo/app/typed/typed.component.ts @@ -30,10 +30,9 @@ export class TypedComponent { "banana" ]; - onDragged( item:any, list:any[] ) { + onDragged( initialIndex: number, list:any[] ) { - const index = list.indexOf( item ); - list.splice( index, 1 ); + list.splice( initialIndex, 1 ); } onDrop( event:DndDropEvent, list:any[] ) { diff --git a/src/dnd-draggable.directive.ts b/src/dnd-draggable.directive.ts index fce69bd..94023f0 100644 --- a/src/dnd-draggable.directive.ts +++ b/src/dnd-draggable.directive.ts @@ -10,9 +10,13 @@ import { } from "@angular/core"; import { calculateDragImageOffset, DndDragImageOffsetFunction, DndEvent, setDragData, setDragImage } from "./dnd-utils"; import { DndHandleDirective } from "./dnd-handle.directive"; -import { dndState, endDrag, startDrag } from "./dnd-state"; +import { dndState, endDrag, getDndInitialIndex, startDrag } from "./dnd-state"; import { EffectAllowed } from "./dnd-types"; +export interface DndDragEvent extends DragEvent { + initialIndex:number | undefined; +} + @Directive( { selector: "[dndDragImageRef]" } ) @@ -39,6 +43,9 @@ export class DndDraggableDirective { @Input() dndType?:string; + @Input() + dndIndex?: number; + @Input() dndDraggingClass = "dndDragging"; @@ -55,19 +62,19 @@ export class DndDraggableDirective { readonly dndStart:EventEmitter = new EventEmitter(); @Output() - readonly dndEnd:EventEmitter = new EventEmitter(); + readonly dndEnd:EventEmitter = new EventEmitter(); @Output() - readonly dndMoved:EventEmitter = new EventEmitter(); + readonly dndMoved:EventEmitter = new EventEmitter(); @Output() - readonly dndCopied:EventEmitter = new EventEmitter(); + readonly dndCopied:EventEmitter = new EventEmitter(); @Output() - readonly dndLinked:EventEmitter = new EventEmitter(); + readonly dndLinked:EventEmitter = new EventEmitter(); @Output() - readonly dndCanceled:EventEmitter = new EventEmitter(); + readonly dndCanceled:EventEmitter = new EventEmitter(); @HostBinding( "attr.draggable" ) draggable = true; @@ -113,7 +120,7 @@ export class DndDraggableDirective { } // initialize global state - startDrag( event, this.dndEffectAllowed, this.dndType ); + startDrag( event, this.dndEffectAllowed, this.dndType, this.dndIndex ); setDragData( event, {data: this.dndDraggable, type: this.dndType}, dndState.effectAllowed ); @@ -144,7 +151,12 @@ export class DndDraggableDirective { } @HostListener( "dragend", [ "$event" ] ) - onDragEnd( event:DragEvent ) { + onDragEnd( event:DndDragEvent ) { + + // Set the initial index of the item on the event, so users can get the + // correct index for drag source manipulation or removal + // https://github.com/reppners/ngx-drag-drop/issues/17 + event.initialIndex = getDndInitialIndex(); // get drop effect from custom stored state as its not reliable across browsers const dropEffect = dndState.dropEffect; diff --git a/src/dnd-state.ts b/src/dnd-state.ts index c0ae254..d12c4e7 100644 --- a/src/dnd-state.ts +++ b/src/dnd-state.ts @@ -13,21 +13,24 @@ export interface DndState { dropEffect?:DropEffect; effectAllowed?:EffectAllowed; type?:string; + initialIndex?: number; } const _dndState:DndState = { isDragging: false, dropEffect: "none", effectAllowed: "all", - type: undefined + type: undefined, + initialIndex: undefined }; -export function startDrag( event:DragEvent, effectAllowed:EffectAllowed, type:string | undefined ) { +export function startDrag( event:DragEvent, effectAllowed:EffectAllowed, type:string | undefined, initialIndex:number | undefined ) { _dndState.isDragging = true; _dndState.dropEffect = "none"; _dndState.effectAllowed = effectAllowed; _dndState.type = type; + _dndState.initialIndex = initialIndex; event.dataTransfer.effectAllowed = effectAllowed; } @@ -38,6 +41,7 @@ export function endDrag() { _dndState.dropEffect = undefined; _dndState.effectAllowed = undefined; _dndState.type = undefined; + _dndState.initialIndex = undefined; } export function setDropEffect( event:DragEvent, dropEffect:DropEffect ) { @@ -114,4 +118,9 @@ export function isExternalDrag():boolean { return _dndState.isDragging === false; } +export function getDndInitialIndex (): number | undefined { + + return _dndState.initialIndex; +} + export const dndState:Readonly = _dndState as Readonly;