angular / components

Component infrastructure and Material Design components for Angular
https://material.angular.io
MIT License
24.34k stars 6.74k forks source link

drag-drop: make the view scroll when trying to move a draggable outside the current view #13588

Closed lfroment0 closed 5 years ago

lfroment0 commented 6 years ago

Bug, feature request, or proposal:

When trying to drag a cdkDragItem outside of the view, it does not scroll to show the rest of the cdkDrop div / the rest of the page.

What is the expected behavior?

The view should scroll towards the direction in which the element is being dragged to reveal the rest of the page.

What is the current behavior?

The view doesn't scroll, the droppable item cannot move out of the current view

What are the steps to reproduce?

In the following stackblitz, try to drag an item from the start of the list to the bottom of the list. https://stackblitz.com/edit/angular-emaoau

What is the use-case or motivation for changing an existing behavior?

The current behaviour feels very restrictive. you could have to take multiple steps if you want to drag and drop an element in a larger list.

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

crisbeto commented 6 years ago

There's been a TODO for it, but I've mostly held back until now since it's tricky figuring out which element should be scrolled.

sanketi commented 6 years ago

Is there any intermediate way to make it work with dom-autoscroller until TODO is addressed? https://github.com/hollowdoor/dom_autoscroller

JohnKis commented 5 years ago

@crisbeto I've implemented auto scrolling on CdkDropList in my private fork. It doesn't cover scenarios where the drop list is wider/taller than its scroll parent but it works fine when the drop list fits on the screen. If you think it'd be useful, I can set aside some time to prepare a PR.

crisbeto commented 5 years ago

@JohnKis the scrolling logic here isn't really the issue. We've held back on implementing it until now, because it's tricky knowing which element we're supposed to scroll.

JohnKis commented 5 years ago

@crisbeto Understood, just figured I’d ask. Thanks

abdulkareemnalband commented 5 years ago

@crisbeto I think we could use cdk-scrollable as marker for element to scroll

ghost commented 5 years ago

Hi guys. Any ideas on when to expect the fix?

rimvydas-urbonas commented 5 years ago

Hey, any update on this thread?

varminas commented 5 years ago

Hi. I have a business case where multiple (say more than 10) containers are stacked vertical. So, need to think about this case as well while implementing auto-scrolling. Maybe for this solution it's possible to incorporate event cdkDropListEntered.

lfroment0 commented 5 years ago

The cdkDropListEntered event already exists (cdkDragEntered), but doesn't solve the problem.

eg. the case where your dropzones are in a scrollable container and the height of a drop zone is greater than the one of the container, so as only one dropZone is displayed. The supposed cdkDropListEntered event will never be emitted.

Would it be possible to make a CdkdropListGroup aware of it's container, so that it can be conscious of how it should behave when moving an item towards the displayed edges of that container?

agent0 commented 5 years ago

I have been trying to come up with a work-around that does not rely on specific functionality by the component library. My approach was to add transparent divs at the top and the bottom of the scrollable container und to watch for mouseenter/mouseleave events to scroll the container. Unfortunately, this did not work as the framework stops the propagation of these events. I don't know if this behavior could be chanhged more easily than coming up with brand new concepts to deal with the matter.

ghost commented 5 years ago

Any updates so far?

ghost commented 5 years ago

I have been trying to come up with a work-around that does not rely on specific functionality by the component library. My approach was to add transparent divs at the top and the bottom of the scrollable container und to watch for mouseenter/mouseleave events to scroll the container. Unfortunately, this did not work as the framework stops the propagation of these events. I don't know if this behavior could be chanhged more easily than coming up with brand new concepts to deal with the matter.

Can you just watch for window.height and window.width and check, if the container extends further, then if it is drag action, then if mouse is down (meaning something is being dragged), then scroll the page accordingly?

abdulkareemnalband commented 5 years ago

@aidvb I have a solution but it comes with its own problems see repro example in #14098

agent0 commented 5 years ago

@aidvb Maybe this would work with scrolling the entire page, in my use case, however, I would like to scroll individual divs. Also, I am not sure if I need browser events to capture the mouse actions and since material cancels the event popagation, I would end up where I started.

ghost commented 5 years ago

@agent0 How's it going to solve the problem?

fromage9747 commented 5 years ago

+1 for this

agent0 commented 5 years ago

@aidvb It would not solve the problem as such but it would enable me to implement my own scrolling trigger to scroll the underlying div manually. As it stands now, I cannot detect that the drag is hovering a border area of the div.

RobinBomkampDv commented 5 years ago

+1 for this

ghost commented 5 years ago

Any progress on solving this issue?

techy2493 commented 5 years ago

Definitely going to +1 this. We're getting ready to implement a work-around using the cdkDragMoved event but that feels like a really poor decision for long run.

codeweazel commented 5 years ago

Would love to have a solution for this. Need to scroll something out of the viewport.

TheKeymaster commented 5 years ago

Is there any workaround for this? I really need this because I have not that much space and I want to allow users to drag and drop inside a small container that is scrollable.

techy2493 commented 5 years ago

@TheKeymaster The CDK drag&Drop currently calculates drop position in such a way that moving the scroll position of the container while dragging interferes with this calculation. Any work-around to detect the hover position of the drug object is limited by that. If you are There is an open issue to address that concern #14098 as well.

shyamal890 commented 5 years ago

+1 Any temporary fix for this?

abdulkareemnalband commented 5 years ago

@shyamal890 you can use repro code from #14098 as starting point also follow up with this https://github.com/angular/material2/issues/14098#issuecomment-450958865

ghost commented 5 years ago

How are the things going? Any chances this issue gonna be fixed?

techy2493 commented 5 years ago

Would love to hear anything about this. Is there any feedback we can provide to help answer any use case questions? Is this not moving because of a priority thing or are there still open questions that need to be answered before the Angular team can move forward that we could be addressing?

oliwin commented 5 years ago

I figured out, that drag zone is escaped when exist scroll in parent list block. To move need drag element in invisible area under scroll

ghost commented 5 years ago

So did anyone manage to come up with a solution in two months time?

techy2493 commented 5 years ago

@aidvb I ended up listening to cdkDragMoved detecting where the cursor was in relation to the container, and scrolling the container a specific interval. This works, but you must additionally modify source (provided in a separate issue linked here) due to a separate bug to address the scroll position of the container not being reflected in the drop position of the elements. So far it seems work for me every time without any unexpected behavior. Smooth scrolling isn't easy and we opted not to try to get it to work but could probably be achieved with some intense math.

ghost commented 5 years ago

@techy2493 Very nice to hear that. Is your update gonna be merged into future release sometime soon?

techy2493 commented 5 years ago

@aidvb I doubt it. My use case doesn't encompass every scenario raised here. In my case I have a single container which is scollable and a single drop list, it's pretty minimal. There are some great questions raised here that the Angular team has to consider, what does happen if there are two scrollable lists, which done do you scroll? How do you switch between them? What if those in turn turn out to be in a scrollable container? It might be nice to see some basic functionality added that doesn't take these things into consideration and see if anyone can come up with additional input or maybe some sample code that would help the more complex use cases.

@crisbeto I could put in a PR with the code from #14098 with the requite additional tests and documentation if that would allow others to more easily get sample solutions set up as example for how this might be tackled if that would be helpful?

willbeaufoy commented 5 years ago

+1 for this

ansarisufiyan777 commented 5 years ago

Did anyone get the solution?

volser commented 5 years ago

@crisbeto any news about auto-scrolling functionality? it's really breaking issue, thx

tricky figuring out which element should be scrolled.

you can just add Input like scrollContainer (or list of containers)

volser commented 5 years ago

Is there any intermediate way to make it work with dom-autoscroller until TODO is addressed? https://github.com/hollowdoor/dom_autoscroller

I tried, dom_autoscroller doesn't work here ( I guess because some events are prevented and need to recalc cached data

ghost commented 5 years ago

@crisbeto Really, what's the update on this issue? Why no one at Angular team solving this problem?

volser commented 5 years ago

Anybody has workaround solution? I'm able to scroll when drag, but can't to fix positions. Tried to recalc _itemPositions but looks like it's not enough (

volser commented 5 years ago

My workaround solution (not finished): https://stackblitz.com/edit/angular-drag-scroll1

Its not a perfect solution but could be a good start point.

tried to fix next issues:

  1. Scroll while dragging

  2. Incorrect item position when drag between vertical positioned containers https://github.com/angular/material2/issues/15227

  3. D&d does not work correctly when change data while dragging (drop containers and drag items) https://github.com/angular/material2/issues/15343

feel free to fix issues found or propose better solutions Need to implement correct syncItems logic

wilgert commented 5 years ago

My workaround solution (not finished): https://stackblitz.com/edit/angular-drag-scroll1

Its not a perfect solution but could be a good start point.

tried to fix next issues:

  1. Scroll while dragging
  2. Incorrect item position when drag between vertical positioned containers

    15227

  3. D&d does not work correctly when change data while dragging (drop containers and drag items)

    15343

feel free to fix issues found or propose better solutions Need to implement correct syncItems logic

If you put the code of your solution in a public repo on GitHub we can collaborate on it!

elirenato commented 5 years ago

+1 Same problem

volser commented 5 years ago

@wilgert pushed here https://github.com/volser/cdk-drag-scroll as is

sgibson53 commented 5 years ago

Any update on this? It's a fundamental feature for drag/drop

DaanSchoukens commented 5 years ago

+1

Matheusqf commented 5 years ago

+1

Musuel commented 5 years ago

Hello,

To suit my needs, I developped a directive allowing a drop list to automatically scroll horizontally/vertically and refresh drop positions. Simply put the dropListScroller directive on the CdkDropList. Note that I had to use a private property of DropListRef: _itemPositions.

Here is the stackblitz: drop-list-scroller

Limitations: Dragging items from another list isn't supported. See @volser previous posts and interesting work. I'll try to have a look on this if I find some time.

@crisbeto Do you think it would be possible to make _itemPositions public in DropListRef ? What do you think about this kind of directive ?

ghost commented 5 years ago

Wonderful! When is this going to be merged?

volser commented 5 years ago

also added a directive vsDragScroll https://github.com/volser/cdk-drag-scroll

npm install --save cdk-drag-scroll

use:

<div
  *ngFor="let item of items"
   cdkDrag
   vsDragScroll
   [vsDragScrollContainer]="scrollContainer"
   [cdkDragData]="item">
   ...
</div>
yatz3000 commented 5 years ago

Has anybody worked out a solution that does not use dragDropList? @volser 's solution looks pretty good, but my use case cannot use dragDropList.

When will this feature be merged into Angular?