Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dragDrop] On strict movement when dropping outside cdkDropList #17351

Open
doyeonOh opened this issue Oct 10, 2019 · 8 comments
Open

[dragDrop] On strict movement when dropping outside cdkDropList #17351

doyeonOh opened this issue Oct 10, 2019 · 8 comments
Labels
area: cdk/drag-drop feature This issue represents a new feature or feature request rather than a bug or bug fix P4 A relatively minor issue that is not relevant to core functions
Projects

Comments

@doyeonOh
Copy link

Feature Description

There is one problem with this, because of some action after dragging on cdkDragDrop.

  1. Drag the item.
  2. Go through the drop zone.
  3. Drop outside the drop zone.

In the case of dragDrop in angular / cdk, when dropping outside the drop zone, the item moves to the last drop zone where the item was entered.

cdk

In the dragula, apart from entering the drop zone, it returns to its original state when dropped outside the drop zone.

dragula

Therefore, it would be nice to provide an strict method of returning to angular / cdk dragdrop as an option.

Please let me know if there is a way around this.

thank you

@doyeonOh doyeonOh added the feature This issue represents a new feature or feature request rather than a bug or bug fix label Oct 10, 2019
@muellerdberlin
Copy link

@doyeonOh how did you solve the issue? did you use different elements than cdk or was it possible to return the element to it's origin list?

@muellerdberlin
Copy link

I got a solution: You can use the attribute isPointerOverContainer: true|false of the (cdkDropListDropped)=drop($event) Event.

@doyeonOh
Copy link
Author

@muellerdberlin
I had to be able to use the private variable _dropContainer of CdkDrag.

However, since typescript does not allow private access, it is solved through @ ts-ignore, which ignores type checking.

I wrote the code by referring to the
drag-ref.ts of angular.

Here is the code that worked.

private moveToOriginDropList(cdkDrag: CdkDrag) {
    // @ts-ignore
    const dragRef = this.cdkDrag._dragRef;
    // @ts-ignore
    const initialContainer = dragRef._initialContainer;
    // @ts-ignore
    dragRef.exited.next({item: dragRef, container: dragRef._dropContainer});
    // @ts-ignore
    dragRef._dropContainer.exit(dragRef);
    // @ts-ignore
    dragRef.entered.next({item: dragRef, container: initialContainer});
    // @ts-ignore
    dragRef._dropContainer = initialContainer;
    // @ts-ignore
    dragRef._dropContainer.enter(dragRef, 0, 0);
  }

@muellerdberlin
Copy link

Thank you!
Here my code which also works perfectly as long as you use the drop event only on a DropList.

move(event: CdkDragDrop<Element>, listToMoveIn) {

        // check if pointer was over another list, otherwise cancel
        if (event.isPointerOverContainer) {
             // move the element to another list
        }

}

@mmalerba mmalerba added the needs triage This issue needs to be triaged by the team label May 20, 2020
@crisbeto crisbeto added area: cdk/drag-drop P4 A relatively minor issue that is not relevant to core functions and removed needs triage This issue needs to be triaged by the team labels May 26, 2020
@crisbeto crisbeto added this to Triaged in triage #1 via automation May 26, 2020
@agrt56
Copy link

agrt56 commented Jul 28, 2021

The attribute isPointerOverContainer: true|false of the (cdkDropListDropped)=dropped($event) event is useful to evaluate wether the item should be allowed to drop or not, but there is no possibility to influence the placeholder, which is still at an unwanted position. A strict mode like shown in the draggula example or requested by @doyeonOh, which resets the placeholder position when the dragged item is leaving a droplist, would be very helpful.

A possible solution could be an event that triggers on exiting an droplist while not entering another... cdkDropListExited is no help there, while cdkDragMoved doesnt include informations wether the dragged item is currently over a droplist or not.

@angular-robot
Copy link
Contributor

angular-robot bot commented Feb 22, 2022

Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.

Find more details about Angular's feature request process in our documentation.

@angular-robot
Copy link
Contributor

angular-robot bot commented Mar 14, 2022

Thank you for submitting your feature request! Looks like during the polling process it didn't collect a sufficient number of votes to move to the next stage.

We want to keep Angular rich and ergonomic and at the same time be mindful about its scope and learning journey. If you think your request could live outside Angular's scope, we'd encourage you to collaborate with the community on publishing it as an open source package.

You can find more details about the feature request process in our documentation.

@Buk1m
Copy link

Buk1m commented May 22, 2023

So here is my super hacky workaround.
It would be nice to have an built in solution as it is extremely confusing with current placeholder behaviour.

I didn't test it too much as this is temp solution. I'm using @angular/cdk 9 in this project so be warned:

	private lastEntered: CdkDropList
	itemEntered($event: CdkDragEnter){
		this.lastEntered = $event.container
	}

	itemMoved(event: CdkDragMove<Item>): void {
		if(this.lastEntered !== event.source.dropContainer && !document.elementsFromPoint(event.pointerPosition.x, event.pointerPosition.y).some(el => el.classList.contains('cdk-drop-list'))){
			this.lastEntered.exit(event.source)
			event.source.dropContainer.enter(event.source, event.pointerPosition.x, event.pointerPosition.y)
			this.lastEntered = event.source.dropContainer
		}
	}

	itemDropped(event: CdkDragDrop<Item>, newStatus): void {
		this.lastEntered = null

		if(!event.isPointerOverContainer || event.container === event.previousContainer) {
			event.item.reset()
			return
		}
	}
	<div
			class="sortable-list"
			cdkDropList
			(cdkDropListDropped)="itemDropped($event, 'pending')"
			[cdkDropListEnterPredicate]="itemStatusNot('pending')"
		>
			<div
				*ngFor="let item of pendingItems"
				class="sortable-box"
				cdkDrag
				(cdkDragMoved)="itemMoved($event)"
				(cdkDragEntered)="itemEntered($event)"
				[cdkDragData]="item"
			>
			<div>
				Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.

			</div>
			</div>
		</div>

dnd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: cdk/drag-drop feature This issue represents a new feature or feature request rather than a bug or bug fix P4 A relatively minor issue that is not relevant to core functions
Projects
No open projects
triage #1
  
Triaged
Development

No branches or pull requests

7 participants