akserg / ng2-dnd

Angular 2 Drag-and-Drop without dependencies

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

No events are fired when dropping outside of sortable container after being hovered over the container

nabc opened this issue · comments

  • I'm submitting a ...
    [x] bug report
    [x] feature request
    [ ] question about the decisions made in the repository

  • Do you want to request a feature or report a bug?
    bug

  • What is the current behavior?
    when dragging an item from sortable container A to sortable container B, if the item was hovered and dropped inside container B, item will be added to container B and onDragEnd and onDropSuccess events will be fired, but if the item was hovered on container B but for some reason (slip of the hand on mouse, miscalculation of the height of container or etc.) user were to drop the item outside of container B, item will be added to container B visually but no events are fired.

  • What is the expected behavior?
    when an item is dropped regardless of whether the dropped place is inside the container or not onDragEnd event should be fired(bug)
    when an item is being added to a sortable container there should be an event like onItemAdded (name can be discussed)(new feature)

  • What is the motivation / use case for changing the behavior?
    suppose i have list A which contains a list of unscheduled jobs and list B which contains scheduled jobs and by dragging jobs from list A to B, jobs will be scheduled.
    in such cases when no event is fired when an item is added to a sortable container , it is extremely difficult to keep track of the jobs in list A and B (unless i check them in angular zone or doCheck which makes application slow and if this includes an API call things will get worse!)

  • Please tell us about your environment:

  • Angular version: 4.3.1
  • Browser: Chrome 61
  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)

I have added a temporary workaround/fix in #232

I think #232 isn't about this. In that case you use onDropSuccess method, but in this case onDropSuccess doesn't work.

if the item was hovered on container B but for some reason (slip of the hand on mouse, miscalculation of the height of container or etc.) user were to drop the item outside of container B, item will be added to container B visually but no events are fired

I noticed that event onDragEndCallback is fired in this case, but args = this._dragDropService.dragData = null

    _onDragEndCallback(event: Event) {
        // console.log('_onDragEndCallback. end dragging elem with index ' + this.index);
        this._sortableDataService.isDragged = false;
        this._sortableDataService.sortableContainer = null;
        this._sortableDataService.index = null;
        this._sortableDataService.markSortable(null);
        // Add dragGata
        this._dragDropService.isDragged = false;
        this._dragDropService.dragData = null;                             // <- ???
        this._dragDropService.onDragSuccessCallback = null;
        //
        this.onDragEndCallback.emit(this._dragDropService.dragData);
    }

This is good, i can examine the lists if any event is being fired, it's a bit crude but it works,thanks!

It's not pretty, but I came up with a solution. I needed a way to detect dragend events globally, regardless of container. In DragDropService I added a new EventEmitter<Event>:

onGlobalDragEndCallback: EventEmitter<Event> = new EventEmitter<Event>();

In abstract.component.ts I emit this event in the ondragend function:

this._elem.ondragend = (event: Event) => {
        if (this._elem.parentElement && this._dragHelper) {
            this._elem.parentElement.removeChild(this._dragHelper);
        }

        // console.log(this._dragDropService);
        this._onDragEnd(event);

        /*
        * Fixes a bug where dragging an item from one sortable container to another and then dropping outside of that container never emits
        * an event.
        */
        this._dragDropService.onGlobalDragEndCallback.emit(event);

        // Restore style of dragged element
        let cursorelem = (this._dragHandle) ? this._dragHandle : this._elem;
        cursorelem.style.cursor = this._defaultCursor;
    };
}

Finally, in the constructor of my component, I subscribe to this event:

constructor(private _dragDropService: DragDropService) {
        
    // Fix for overcoming issue with ng2-dnd bug.
    this._dragDropService.onGlobalDragEndCallback.subscribe(g => {
        this.stopDragging();
    });
        
}

It looks like something is happening where an array of observers gets unset when you drag the element out of the new sortable container. There is probably a much more elegant solution, but this works for now!