Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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));
}
Expand Down Expand Up @@ -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]"
} )
Expand All @@ -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;

Expand Down
15 changes: 9 additions & 6 deletions demo/app/typed/typed.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
class="dndPlaceholder">
</mat-list-item>

<mat-list-item *ngFor="let fruit of fruits"
<mat-list-item *ngFor="let fruit of fruits; let i = index"
[dndDraggable]="fruit"
[dndType]="fruit"
[dndIndex]="i"
dndEffectAllowed="move"
(dndMoved)="onDragged(fruit, fruits)">
(dndMoved)="onDragged($event.initialIndex, fruits)">
<h1 mat-line>{{fruit}}</h1>
</mat-list-item>

Expand All @@ -40,11 +41,12 @@ <h1 mat-line>{{fruit}}</h1>
class="dndPlaceholder">
</mat-list-item>

<mat-list-item *ngFor="let apple of apples"
<mat-list-item *ngFor="let apple of apples; let i = index"
[dndDraggable]="apple"
[dndType]="apple"
[dndIndex]="i"
dndEffectAllowed="move"
(dndMoved)="onDragged(apple, apples)">
(dndMoved)="onDragged($event.initialIndex, apples)">
<h1 mat-line>{{apple}}</h1>
</mat-list-item>

Expand All @@ -65,11 +67,12 @@ <h1 mat-line>{{apple}}</h1>
class="dndPlaceholder">
</mat-list-item>

<mat-list-item *ngFor="let banana of bananas"
<mat-list-item *ngFor="let banana of bananas; let i = index"
[dndDraggable]="banana"
[dndType]="banana"
[dndIndex]="i"
dndEffectAllowed="move"
(dndMoved)="onDragged(banana, bananas)">
(dndMoved)="onDragged($event.initialIndex, bananas)">
<h1 mat-line>{{banana}}</h1>
</mat-list-item>

Expand Down
5 changes: 2 additions & 3 deletions demo/app/typed/typed.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[] ) {
Expand Down
28 changes: 20 additions & 8 deletions src/dnd-draggable.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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]"
} )
Expand All @@ -39,6 +43,9 @@ export class DndDraggableDirective {
@Input()
dndType?:string;

@Input()
dndIndex?: number;

@Input()
dndDraggingClass = "dndDragging";

Expand All @@ -55,19 +62,19 @@ export class DndDraggableDirective {
readonly dndStart:EventEmitter<DragEvent> = new EventEmitter<DragEvent>();

@Output()
readonly dndEnd:EventEmitter<DragEvent> = new EventEmitter<DragEvent>();
readonly dndEnd:EventEmitter<DndDragEvent> = new EventEmitter<DndDragEvent>();

@Output()
readonly dndMoved:EventEmitter<DragEvent> = new EventEmitter<DragEvent>();
readonly dndMoved:EventEmitter<DndDragEvent> = new EventEmitter<DndDragEvent>();

@Output()
readonly dndCopied:EventEmitter<DragEvent> = new EventEmitter<DragEvent>();
readonly dndCopied:EventEmitter<DndDragEvent> = new EventEmitter<DndDragEvent>();

@Output()
readonly dndLinked:EventEmitter<DragEvent> = new EventEmitter<DragEvent>();
readonly dndLinked:EventEmitter<DndDragEvent> = new EventEmitter<DndDragEvent>();

@Output()
readonly dndCanceled:EventEmitter<DragEvent> = new EventEmitter<DragEvent>();
readonly dndCanceled:EventEmitter<DndDragEvent> = new EventEmitter<DndDragEvent>();

@HostBinding( "attr.draggable" )
draggable = true;
Expand Down Expand Up @@ -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 );

Expand Down Expand Up @@ -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;
Expand Down
13 changes: 11 additions & 2 deletions src/dnd-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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 ) {
Expand Down Expand Up @@ -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> = _dndState as Readonly<DndState>;