peppermcknight peppermcknight - 28 days ago 33
TypeScript Question

Angular2 Drag and Drop Target

I'm implementing a drag and drop feature in my angular2 application that works like this... A user sees a list of options that they may choose from and a drop zone above the list - when they drag from one of the options into the drop zone then the event is handled.

So far, I have a draggable directive that handles the drag start event and sets some data on the dataTransfer attribute of the event. What I have tried to do is make another directive that is a dropTarget directive that handles simply the drop event and grabs the data.

Is this something that is possible to do? Would I be better just using the same directive for the draggable divs and the drop zone and inserting some logic to only allow the drop event to take place when the div is dropped on the right target.

Thanks

EDIT: Code

Here is the code for my draggable directive:

import {Directive, ElementRef} from '@angular/core';

@Directive({
selector: '[myDraggable]',
host: {
'(dragstart)': 'onDragStart($event)',
'(dragover)': 'onDragOver($event)',
'(dragleave)': 'onDragLeave($event)',
'(dragenter)': 'onDragEnter($event)',
'(drop)': 'onDrop($event)'
}
})
export class DraggableDirective {

constructor(el: ElementRef) {
el.nativeElement.setAttribute('draggable', 'true');
}

onDragStart(ev: DragEvent) {
console.log("Drag Started");
ev.dataTransfer.setData('Text', 'Data from drag start');
}

}


and here is the drag target directive code:

import {Directive, ElementRef} from '@angular/core';

@Directive({
selector: '[dragTarget]',
host: {
'(dragover)': 'onDragOver($event)'
}
})
export class DragTargetDirective {

onDragOver(ev: DragEvent) {
console.log("dragged over target" + ev.dataTransfer.getData('Text'));
}

}


and finally here is the html that contains both directives

<div class="relativeContainer">
<div class="absoluteBox" *ngFor="let process of processes" [ngClass]="{'active': process.active}">
<div class="process-title">{{process.stage}} - {{process.name}}</div>
<div dragTarget *ngIf="process.options" class="process-selection">{{process.options[process.selectedOption]}}</div>
<ul class="option-list">
<li myDraggable *ngFor="let option of process.options" class="option-item"><p>{{option}}</p></li>
</ul>
</div>




I also have the metadata for the component with the directives imported and declared here

import {DraggableDirective, DragTargetDirective} from '../draggable';

@Component({
templateUrl: 'app/dashboard/dashboard.component.html',
styleUrls: [require('./dashboard.component.scss')],
directives: [DraggableDirective, DragTargetDirective]
})

Answer

Thought I'd come and complete this question - I was using the wrong event handler function - trying to get the data from the event on dragover was something that I wasn't intending to do.

The ondrop function was the right one to use and worked exactly how I was expecting it to.