swimlane / ngx-dnd

🕶 Drag, Drop and Sorting Library for Angular2 and beyond!
https://swimlane.github.io/ngx-dnd/
MIT License
574 stars 136 forks source link

Cancel after drop? #5

Open gdahlin opened 7 years ago

gdahlin commented 7 years ago

Hi, are there any plans or documentation to be able to cancel an ongoing drop from code?

(e.g when the underlying logic that handles the drop event goes wrong, and you want to put the item back to its original place/container)

Hypercubed commented 7 years ago

I don't have any plans, but willing to look at a PR. Please be aware that we are still actively working on this module... many things may change.

gdahlin commented 7 years ago

Alright, good to know. I have (somewhat inefficient) workarounds at the moment, but will probably do some work on a PR then in a while. I'm thinking on a onBeforeDrop event where it's possible to cancel the drag on drake/dragula. Thoughts on that?

Hypercubed commented 7 years ago

I believe a onBeforeDrop event would be useful for many. Within the onBeforeDrop we should be able to modify the item model (especially if the the container is set to copy the model rather than move) and cancel the drop.

Souvik93 commented 7 years ago

Ok please add it . It will be very helpful .

Hypercubed commented 7 years ago

Currently the best way to prevent a drop is to set restrictive drop zones. I've found that this is all that is needed in most cases. That said a onBeforeDrop event would be useful and PRs are welcome.

fperezgaliana commented 7 years ago

Hi! I'm doing some tests with your module and it does basically all I need except this specific feature. I have a source 'object' palette which I can drag into 5 containers. This is the easy part, the difficult one is that I need to control the objects before they're dropped into the containers, as not all objects can go into all of the containers, and also some objects can't be dropped in a container that has already one of them.

Is there any way to do this? As there's no 'onBeforeDrop' event right now, would it be difficult to implement this logic inside the 'onDrop' event?

Thanks a lot, cheers!

rtalexk commented 6 years ago

I came here for the same reason. I need make an HTTP request when dropping an item, but if something went wrong, I need to revert changes.

The use case is as follows:

image

When I drop a food into a menu, food div is cloned and would be great if I cancel node addition and instead just push one more food into menu.foods array, something like this:

onDropSuccess(data) {
  this.menuProv.addFoodToMenu(this.menu.id, data).subscribe(
    res => {
      this.menu.foods.push(data);
    }, err => {
      this.notify({ type: 'error', msg: err.message });
    });
}

menu.foods array is added to view with an *ngFor, so I just need to push to add one more item but not clone source node into droppable zone.

EDIT: How I achieve this?

on drop event I just remove the current added item:

HTML container

<div ngxDroppable (drop)="onDropSuccess($event)"></div>

TS:

onDropSuccess(ev) {
  console.log(ev);
  ev.el.parentNode.removeChild(ev.el);
  // Add logic for HTTP request and pushing item.
}
altschuler commented 6 years ago

You can achieve this using the dropped event and a dragula method. Inject ngx-dnd's DrakeStoreService, and in your dropped handler, call drake.cancel(true). Docs on cancel here.

So, something to the effect of:

// Component
@Component({...})
export class Foo {
    constructor(private drakeStore: DrakeStoreService) {}

    public dropped(x: any) {
        if (!x.is.legit) {
            // We need the cast because the dragula instance is actually private
            (this.drakeStore as any).drake.cancel(true);
        }
    }
}

// Template
<div ngxDroppable="foo" (drop)="dropped($event)"></div>
bharathmuppa commented 6 years ago

@altschuler this method not working for me . My scenario is onDrop, i need to do a service call and on error of that service call, I need to cancel it.

neil-coutinho commented 6 years ago

@altschuler According the docs, when copy is set to true the drake.cancel(true) has no effect.

@Hypercubed any idea how one can revert the item after drop or perform a check before the item is dropped?