5

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]
})
6
  • Sure it's possible. Can you please add some code that demonstrates what you already tried. Commented May 5, 2016 at 11:23
  • Ok, added the code that I've got so far - basically I want to set some data in the draggableDirective when the drag starts and retrieve it in the dragTargetDirective Commented May 5, 2016 at 11:30
  • What is the problem? Where are you stuck. Is the dragover event handler called? Commented May 5, 2016 at 12:04
  • Yeah the drag over event is called but it doesn't seem to be able to access the data inside the 'Text' attribute that is set inside the other directive the comsole log prints nothing after the hard coded string Commented May 5, 2016 at 12:10
  • Ok, so it looks like the ev.dataTransfer does not return the text on a drag over event, maybe I'm reading the documentation wrong and it can't actually do that, but what I was wanting was it to do that on the drop event - put the drop event in and it is now working. Commented May 5, 2016 at 12:19

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.