jr1982
jr1982

Reputation: 31

Drop events are not firing in AngularDart app however Drag events are firing

my first post on SO!

In short, I'm researching Dart drag & drop libraries for use in an AngularDart project. I have created an example repo (https://bitbucket.org/johnryanancoa/componentdecorator/src/). The tag produces the desired markup, onto which a decorator attaches the relevant events. The Drag events are correctly printing a message to the console when an event fires. However, the Drop events are not firing.

Can anyone shed any light on this please? I'm thinking I'm making mistakes with my use of Futures although would appreciate any pointers.

Thank you in advance. John

UPDATE: adding relevant code snippets from the above repo as per @slawson's suggestion

== main.html ==

<body>
    <my-component class="my-component" my-decorator></my-component>
    ...
</body>

== main.dart ==

import 'package:logging/logging.dart';

import 'package:angular/angular.dart';
import 'package:angular/application_factory.dart';

import 'package:componentDecorator/component/component.dart';
import 'package:componentDecorator/component/decorator.dart';

String _delimiter = "-";

class MyMod extends Module {
    final Logger log = new Logger('componentDecorator');

    MyMod() {
        bind(MyCoolDecorator);
        bind(MyCoolComponent);
    }
}

void main() {
    Logger.root.level = Level.ALL;
    Logger.root.onRecord.listen((LogRecord rec) {
        print('[${rec.level.name}: ${rec.loggerName}] ${_delimiter} ${rec.message}');
    });

    applicationFactory()
            .addModule(new MyMod())
            .run();
}

== component.dart ==

library mycomponent;

import 'dart:core';
import 'dart:html';

import 'package:angular/angular.dart';
import 'package:logging/logging.dart';

@Component(
    selector: 'my-component',
    templateUrl: 'packages/componentDecorator/component/component.html',
    cssUrl: 'packages/componentDecorator/component/component.css',
    publishAs: 'comp'
) class MyCoolComponent {

    MyCoolComponent(final Element element) {
        Logger.root.fine("MyCoolComponent(): element = $element, element.attributes = ${element.attributes.keys}");
    }
}

== component.html ==

<ul dnd dnd-dropzone>
    <li dnd dnd-draggable>one</li>
    <li dnd dnd-draggable>three</li>
    <li dnd dnd-draggable>five</li>
</ul>

<ul dnd dnd-dropzone class="even">
    <li dnd dnd-draggable>two</li>
    <li dnd dnd-draggable>four</li>
    <li dnd dnd-draggable>six</li>
</ul>

== decorator.dart ==

library mydecorator;

import 'dart:core';
import 'dart:html';
import 'dart:async';

import 'package:angular/angular.dart';

import 'package:componentDecorator/dnd/dnd.dart';

@Decorator(
    selector: '[my-decorator]'
) class MyCoolDecorator extends AttachAware {

    final Element element;

    MyCoolDecorator(this.element);

    void attach() {
        new Future(() {
            var _el;
            if (element.shadowRoot != null) {
                _el = element.shadowRoot;
            } else {
                _el = element;
            }

            // common
            print("${_el.hashCode} el: ${_el}");

            print("${_el.hashCode} el.draggable: ${_el.querySelectorAll('[dnd-draggable]').length}");
            Draggable draggable = new Draggable(_el.querySelectorAll('[dnd-draggable]'), avatarHandler: new AvatarHandler.clone())
                    ..onDragStart.listen(onDragStart)
                    ..onDragEnd.listen(onDragEnd)
            ;
            print("${_el.hashCode} draggable: ${draggable}");

            print("${_el.hashCode} el.dropzones: ${_el.querySelectorAll('[dnd-dropzone]').length}");
            Dropzone dropzones = new Dropzone(_el.querySelectorAll('[dnd-dropzone]'), acceptor: new Acceptor.draggables([draggable]))
                    ..onDragEnter.listen(onDragEnter)
                    ..onDragLeave.listen(onDragLeave)
                    ..onDragOver.listen(onDragOver)
                    ..onDrop.listen(onDrop)
            ;
            print("${_el.hashCode} dropzones: ${dropzones}");
        });
    }

    Element getElement() {
        var _el;
        if (element.shadowRoot != null) {
            _el = element.shadowRoot;
        } else {
            _el = element;
        }

        // common
        print("${_el.hashCode} el: ${_el}");
        print("${_el.hashCode} el.dropzones: ${_el.querySelectorAll('[dnd-dropzone]').length}");
        print("${_el.hashCode} el.draggable: ${_el.querySelectorAll('[dnd-draggable]').length}");
        return _el;
    }

    void onDragEnter(DropzoneEvent event) {
        print("onDragEnter()");
    }

    void onDragStart(DraggableEvent event) {
        print("onDragStart()");
    }

    void onDragEnd(DraggableEvent event) {
        print("onDragEnd()");
    }

    void onDragOver(DropzoneEvent event) {
        print("onDragOver()");
    }

    void onDrop(DropzoneEvent event) {
        print("onDrop()");
    }

    void onDragLeave(DropzoneEvent event) {
        print("onDragLeave()");
    }
}

Upvotes: 2

Views: 511

Answers (3)

Adonis Gaitatzis
Adonis Gaitatzis

Reputation: 3729

You must send an event.preventDefault() in your onDrag() handler, or else your drag event will prevent your drop event from firing properly.

import { Component } from "@angular/core";

@Component({
    selector: "my-component",
    template: `
      <div
        (dragover)="onDragOver($event)"
        (drop)="onDrop($event)"
      >
        Drop here
      </div>
    `
});

export class MyComponent {
    void onDragOver(event) {
        event.preventDefault(); // this allows onDrop() to fire later
        print("onDragOver()");
    }

    void onDrop(event) {
        event.preventDefault();
        print("onDrop()");
    }
}

Upvotes: 0

jr1982
jr1982

Reputation: 31

UPDATE!! Modifying the @Component declaration appears to resolve the issue...

Before

@Component(
    selector: 'my-component',
    templateUrl: 'packages/componentDecorator/component/component.html',
    cssUrl: 'packages/componentDecorator/component/component.css',
    publishAs: 'comp'
) class MyCoolComponent {

After

@Component(
    selector: 'my-component',
    templateUrl: 'packages/componentDecorator/component/component.html',
    useShadowDom: false,
    publishAs: 'comp'
) class MyCoolComponent {

I need to investigate further tomorrow but at least it triggers the events and prints to the console! Thanks for your help nonetheless...

Upvotes: 0

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657008

You need to call preventDefault on some drag-n-drop events (dragover) to indicate you will handle the drop event.

http://www.w3schools.com/html/html5_draganddrop.asp http://www.html5rocks.com/en/tutorials/dnd/basics/

Upvotes: 1

Related Questions