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.
The view should scroll towards the direction in which the element is being dragged to reveal the rest of the page.
The view doesn't scroll, the droppable item cannot move out of the current view
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
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.
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.
Is there any intermediate way to make it work with dom-autoscroller until TODO is addressed?
https://github.com/hollowdoor/dom_autoscroller
@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.
@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.
@crisbeto Understood, just figured I’d ask. Thanks
@crisbeto I think we could use cdk-scrollable as marker for element to scroll
Hi guys. Any ideas on when to expect the fix?
Hey, any update on this thread?
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.
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?
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.
Any updates so far?
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?
@aidvb I have a solution but it comes with its own problems
see repro example in #14098
@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.
@agent0 How's it going to solve the problem?
+1 for this
@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.
+1 for this
Any progress on solving this issue?
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.
Would love to have a solution for this. Need to scroll something out of the viewport.
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.
@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.
+1 Any temporary fix for this?
@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
How are the things going? Any chances this issue gonna be fixed?
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?
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
So did anyone manage to come up with a solution in two months time?
@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.
@techy2493 Very nice to hear that. Is your update gonna be merged into future release sometime soon?
@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?
+1 for this
Did anyone get the solution?
@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)
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
@crisbeto Really, what's the update on this issue? Why no one at Angular team solving this problem?
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 (
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:
Incorrect item position when drag between vertical positioned containers
https://github.com/angular/material2/issues/15227
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
My workaround solution (not finished):
https://stackblitz.com/edit/angular-drag-scroll1Its not a perfect solution but could be a good start point.
tried to fix next issues:
- Scroll while dragging
- Incorrect item position when drag between vertical positioned containers
#15227- D&d does not work correctly when change data while dragging (drop containers and drag items)
#15343feel free to fix issues found or propose better solutions
Need to implement correctsyncItems
logic
If you put the code of your solution in a public repo on GitHub we can collaborate on it!
+1 Same problem
@wilgert pushed here https://github.com/volser/cdk-drag-scroll as is
Any update on this? It's a fundamental feature for drag/drop
+1
+1
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 ?
Wonderful! When is this going to be merged?
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>
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?
Hello,
has anyone an idea how to get a reference to the dragged preview element, when it is a copy of the original or general?
The problem I try to solve is that if you drag an element and scroll the page the drag preview
position is not at the position where the mouse position is any more.
i.e. if I scroll the page 500px while dragging the offset between drag preview and mouse/touch point is 500px.
My goal is to at least update the preview position after scrolling to the current mouse/touch point.
also added a directive
vsDragScroll
https://github.com/volser/cdk-drag-scrollnpm install --save cdk-drag-scroll
use:
<div *ngFor="let item of items" cdkDrag vsDragScroll [vsDragScrollContainer]="scrollContainer" [cdkDragData]="item"> ... </div>
this would work on scrollable window? or dnd container must have overflow?
currently only container, but it easily could be adapted for window
Hi Volser,
Using the cdk-drag-scroll making the drag item slow in our application, we have nested drag-drop supports of fields, row, widget, section, column etc. In the demo it is not feelable as it had a simple list.
What about original solution and when will it be implemented in Angular?
I tried @volser solution and it works fine if the scrollable container with fixed height, but doesn't work for the window scroll. (I guess is not meant for that)
We have any update on an official feature, even if it's on todo list?
currently only container, but it easily could be adapted for window
If you can give an example of how you'd use it or implement it with window scroll (knowing that the list might be starting at the unknown position in the scroll and not exactly starting and ending at the top or bottom of the page.)
i guess you can find the list offset from the window container and calculate it.
hi @volser , can this work two scroll containers? vertically in the cdkDropList and horizontally within the cdkDropListGroup (like in a trello board ).
+1 from Italy with love
use https://github.com/volser/cdk-drag-scroll/issues please, to discuss library related stuff
We are waiting for a solution for this too! :)
+1 from Switzerland!
+1 from Berlin
+1 from Tunisia
+1 from Lithuania.
+1 from Israel
Hey guys, Angular 8 is out, great work! Hope it means the team is back on Angular material (or should I say Angular components).
This looks like a great opportunity to start discussing new component features (& bugs) we desperately are waiting for. This is certainly one of them. When I filter the P2 priority issues with most reactions / comments, this is the first one.
Would be awesome to make this thread "buzzing" again.
. from VietNam
Without this functionality our application is in certain situations unused. I have tried all the above listed workarounds, directives, etc, but scrollable elements inside window (outside container) doesn't work. So, big plus from Swiss.
+1 from North Macedonia
@varminas I agree, we are in same situation. For now we are waiting but this is essential for us too.
+1 from the Shires, UK
This works well for me. Have a nice day
https://stackblitz.com/edit/cdk-drop-list-scroll
This works well for me. Have a nice day
https://stackblitz.com/edit/cdk-drop-list-scroll
This doesn't scroll on the parent element(s). It scrolls inside the CDK drop list.
Hi i have tried using this library for my projects ngx-smooth-dnd. Work really well with dnd support and drag on scroll as-well. I have made a sample demo app here https://github.com/sandeepsuvit/angular-dnd-survey-creator
. Here is a working demo of the app that i created using ngx-smooth-dnd
. Hope this helps someone until this issue is fixed :)
@sandeepsuvit. This seems great and it works and behaves as we also want it to.
It can probably solve some peoples scenarios but we would still vote very high for this feature being in the angular cdk.
The problem is that this npm package is not that popular(maybe it will be) and is only in version 0.3.0. We have a very large application and we need bigger teams behind the npm packages.
I still don't understand why this feature is not prioritized more in the angular cdk since this small library made by 1 person can do this even before it's in version 1.x :D
@sandeepsuvit. This seems great and it works and behaves as we also want it to.
It can probably solve some peoples scenarios but we would still vote very high for this feature being in the angular cdk.
The problem is that this npm package is not that popular(maybe it will be) and is only in version 0.3.0. We have a very large application and we need bigger teams behind the npm packages.
I still don't understand why this feature is not prioritized more in the angular cdk since this small library made by 1 person can do this even before it's in version 1.x :D
This is the biggest reason why we don't use alot of "custom" modules too. They often stop getting (critical) updates after a while. We've learned it's best to go with only 100% original modules, or bigger ones, supported by Angular.
BUMP
someone, please...
Any update on this? https://github.com/angular/components/issues/14273#issuecomment-442201350
Also looking forward to this feature :)
Implemented CDK DnD and then found out this feature is missing... can we have a projection as off when this will be implemented?
Finally, that‘s all what we‘ve been waiting for!! Great that this is fixed now.
@crisbeto , when will it be released?
It should be in 8.1.0.
How to make it work?
The update is released, but I cannot see anything changed.
@crisbeto Do you have a StackBlitz example showing how to use this feature? I can't seem to make it work on 8.1.1.
@Achilles1515 it depends on which is your scrollable element. At the moment it's set up to only scroll the window or the list itself. It starts scrolling when you're dragging and the pointer is close to the edge of the element.
@crisbeto I got it working as you say: scroll just the list itself.
To make it work one has to make the list scrollable (fixed height and/or overflow set to auto
).
Is there a way to enable scrolling also in the viewport?
@crisbeto
I also got it to work. In the gif below, is auto-scroll supposed to stop like it does when getting close to the left edge of the container? This does not happen on the right side of the container.
https://stackblitz.com/edit/angular-dggptq
Unfortunately it does not work within a Material Table at all. :( I can scroll with mouse wheel now, but the distance between the drag placeholder and the dragged element is increasing while scrolling.
Unfortunately it does not work within nested cdkDropList. In my case I need mainly vertical auto scroll. In the attached image red circled scorllbar should be scrolled automatically when I try to drop a field in a form section.
Should be able to add directive to the container which we want to be able to scroll y and scroll x
Trying to build a Kanban board and dragging a card won't scroll the parent container horizontally.
but this works only with drop list if i have a box inside a container div when i drag the box it's container is not scrolling ! :/
@crisbeto
When grabbing a scrollable item and going past the bottom of the viewport or past the top of the viewport, the browser window doesn't scroll.
(the container is larger than the browser viewport.)
Is there a way to do this?
I want the same functionality but within a container that is larger than the viewport. (So that the window automatically starts scrolling up or down & no extra scroll bar, just the windows scrollbar.)
This seems like something that should just work out of the box?
That might be because the scroll regions are overlapping. I've got https://github.com/angular/components/pull/16675 to help with it.
+1 for @nkartchner 's stakblitz example. Even if you manually scroll the board when the ticket is being dragged the drop containers do not 'register' so when they scroll into view you still can't drop the ticket on them
@crisbeto hi! are there plans to make this possible for mobile as well?
It should work on mobile already.
Works for me but only for nearest scrollable parent it seems. Also, is there a way to set the scroll speed?
<div> -- has horizontal scroll (new drag scroll feature does not work here)
<div> -- has vertical scroll (new drag scroll feature works here)
<element> -- draggable
</div>
</div>
Works for me but only for nearest scrollable parent. Also, is there a way to set the scroll speed?
<div> -- has horizontal scroll (new drag scroll feature does not work here) <div> -- has vertical scroll (new drag scroll feature works here) <element> -- draggable </div> </div>
need a way to set scroll speed, especially when the list is too long
DND auto scroll
is not working on custom scroll(ngx-scrollbar)
.
Inject Document and set id to container for all drag list items to move the horizontal scrollbar when emitting dragMove event
import { DOCUMENT } from '@angular/common';
import { Inject } from '@angular/core';
constructor(
@Inject(DOCUMENT) private document: Document
) {
}
onDragMoved(event) {
if (event.delta.x === 1) {
this.document.getElementById('container').scrollLeft += 10;
} else {
this.document.getElementById('container').scrollLeft -= 10;
}
}
@Mustafa-Omran can you explain bit more ?
I had made this code, but I just found that it works if updating haha
It works only with overflow:hidden case.
I will stay here if anyone wants to do this in older versions.
This is an object that you place in the document where dragMoved is in function, and call part of it inside dragMoved to work:
//AUTOSCROLL IMPLEMENTATION
autoScrollSetup = {
isOnEdge:false,
itsStarted:false,
scroll(side:any,elContainer:any,everyXms:any,stepPx:any,direction:any):any{
if(this.isOnEdge){ // Mouse in the edge enough to scroll?
if(!this.itsStarted){ // Event already started?
this.itsStarted = true;
// Check the direction
let elScroll:any;elScroll;
if(direction==="horizontal"){
elScroll = "scrollLeft";
}
else
if(direction==="vertical"){
elScroll = "scrollTop";
}
// Runs from time to time
setTimeout(() => {
if(side==="leftOrTop") {elContainer![elScroll] -= stepPx} // It's on the left side (if it's horizontal) or top (if it's vertical) ?
else
if(side==="rightOrBottom") {elContainer![elScroll] += stepPx} // It's on the right side (if it's horizontal) or bottom (if it's vertical) ?
this.itsStarted = false; // Finish
this.scroll(side,elContainer,everyXms,stepPx,direction); // Rerun
}, everyXms);
}
}
},
autoScroll(objConfig:any){
// Set default values
var {event,lateralTolerancePx=40,stepPx=5,everyXms=30,direction='horizontal'} = objConfig;
// Get element Container and this position
var elContainer = event.source.dropContainer.element.nativeElement;
var elContainerBCR = elContainer!.getBoundingClientRect();
// Check direction
let elContainer1:any;
let elContainer2:any;
let xy:any;
if(direction==="horizontal"){
elContainer1 = elContainerBCR.left;
elContainer2 = elContainerBCR.right;
xy = 'x';
}
else
if(direction==="vertical"){
elContainer1 = elContainerBCR.top;
elContainer2 = elContainerBCR.bottom;
xy = 'y';
}
if(event.pointerPosition[xy] <= elContainer1+lateralTolerancePx){ // Is mouse position left/top enough to start scrolling?
this.isOnEdge = true;
this.scroll("leftOrTop",elContainer,everyXms,stepPx,direction);
}
else if(event.pointerPosition[xy] >= elContainer2-lateralTolerancePx){ // Is mouse position right/bottom enough to start scrolling?
this.isOnEdge = true;
this.scroll("rightOrBottom",elContainer,everyXms,stepPx,direction);
}
else{
this.isOnEdge = false;
}
}
}
Inside dragMoved:
dragMoved(event: CdkDragMove<string[]>){
//Auto Scroll: event*(required), direction(horizontal or vertical), lateralTolerancePx, stepPx, everyXms
this.autoScrollSetup.autoScroll({'event':event,'direction':'horizontal'})
}
besides calling dragMoved inside each list element.
It worked well with me and I tried to make it very easy to deploy.
@Mustafa-Omran can you explain bit more ?
HTML
<div class="container" id="container">
<h4 class="title">Itmes</h4>
<div class="overflow-container" cdkDropList (cdkDropListDropped)="onDropItem($event)"
[cdkDropListData]="items">
<ul *ngFor="let item of items" class="item" [cdkDragData]="item" cdkDrag
(cdkDragMoved)="onDragMoved($event)">
<app-item [item]="item">
</app-item>
</ul>
</div>
</div>
TS
onDragMoved(event) {
if (event.delta.x === 1) {
this.document.getElementById('container').scrollLeft += 10;
} else {
this.document.getElementById('container').scrollLeft -= 10;
}
}
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
_This action has been performed automatically by a bot._
Most helpful comment
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?