Skip to content

Bug: Drag and Drop not working inside MatDialog (wrong previous and current index) #15880

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

Closed
betancourtc opened this issue Apr 23, 2019 · 27 comments
Labels
area: cdk/drag-drop P4 A relatively minor issue that is not relevant to core functions

Comments

@betancourtc
Copy link

betancourtc commented Apr 23, 2019

What is the expected behavior?

Reorder items in a list inside Mat-dialog using Angular Material Drag and Drop.

What is the current behavior?

Drag and drop does not work properly on the last items of the list. Previous and current index are the same in the moveItemInArray function

What are the steps to reproduce?

I have an array, where each item contains a list of colors. Clicking the edit button opens an Angular Material Dialog with the list of colors (for that item). The colors can be reordered using drag and drop. The list of colors from the first items of the list work fine, but when trying to reorder the list of colors in the last items of the list, drag and drop does not work. I did some debugging and found out that for the items not working, the event passed to the moveItemInArray, has the same number for the current and the previous index.

As previously mentioned, click on the edit button for one of the first items in the list and try reordering the colors, it works fine, choose the last item in the list and you will see the colors cannot be reordered, take a look at the console to get the previous and current indexes.

StackBlitz starter: https://stackblitz.com/edit/angular-u6dt7a

Not sure whether this is a CDK or a Mat-Dialog dialog.

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

Angular 7, Angular Material 7.3.7
Chrome, Firefox

Is there anything else we should know?

When reducing the list of items to just a couple of them, then all list of colors for all items work fine. Problem starts when the list of items starts to grow in number.

@Airblader
Copy link
Contributor

Airblader commented Apr 24, 2019

I'm having the suspicion that this somehow has to do with MatDialog. I've also observed that sometimes the indices are different, but still not correct. It also seems to only happen in combination with cdkDropList, a standalone cdkDrag works fine.

For the record, the data passed to the dialog doesn't matter – you can even pass a static array and observe the same effect.

@betancourtc betancourtc changed the title Bug: Drag and Drop not working (wrong previous and current index) Bug: Drag and Drop not working inside MatDialog (wrong previous and current index) Apr 25, 2019
@betancourtc
Copy link
Author

I wasn't sure either where the problem was, but as you mentioned it might be on the MatDialog side and not the CDK. Any ideas on how to get this working? I don't see any errors on the console, so don't really know where to start looking to get a fix for this.

@Airblader
Copy link
Contributor

It seems to correlate of the combination of opening a dialog when you have scrolled the page.

Try this: make the window as big as possible, load the app and open the dialog for the most bottom item without scrolling; it works fine. Now make the window smaller, reload the app, scroll to the same item and edit it again; it will now break.

As you can also see, when a dialog opens, somehow the body scroll disappears, which I assume is intended behavior for dialogs. I think this somehow interferes with the calculations done for the drag/drop translate styles.

@Airblader
Copy link
Contributor

Airblader commented Apr 26, 2019

Disabling the cdk-global-scrollblock class applied to the <html> tag when modals open makes the issue disappear.

Edit: If cdk-global-scrollback is applied to body rather than html it also seems to work. I'm sure this would break something else, of course. ;-)

html.cdk-global-scrollblock {
    position: initial !important;
}

html.cdk-global-scrollblock body {
    position: fixed;
}

@Airblader
Copy link
Contributor

@betancourtc I think a workaround would be to inject a MAT_DIALOG_SCROLL_STRATEGY that does not use the block scroll strategy. This is of course suboptimal since you probably do not want to allow scrolling while a modal is open – it should make the drag and drop work for now, though.

@Airblader
Copy link
Contributor

This is about as far as I was able to get. I think it would be good if the people working on drag and drop could weigh in now, at least we identified that the issue is the scrollblock.

@betancourtc
Copy link
Author

@Airblader Thanks a lot for your help. I hope too the people working on the drag and drop module take a look at this. Cheers

@andrewseguin
Copy link
Contributor

I'm unable to reproduce the issue, the drag and drop seems to be working correctly. Can you confirm it is breaking and let me know what browser and version you are using?

@andrewseguin andrewseguin added needs: clarification The issue does not contain enough information for the team to determine if it is a real bug P4 A relatively minor issue that is not relevant to core functions labels May 7, 2019
@betancourtc
Copy link
Author

@andrewseguin I was able to reproduce the issue trying to drag and drop the colors on the last theme (number 50) from my example in StackBlitz on Chrome Version 73.0.3683.103 (64-bit) and on Firefox Version 66.0.3 (64-bit). Both on Windows 10.

@Airblader
Copy link
Contributor

Airblader commented May 8, 2019

@andrewseguin The problem only occurs when you click "Edit" on one of the items on the bottom if you had to scroll (significantly). If you have a big monitor, make sure to resize the window to something small so you need to scroll down first.

I am absolutely able to reproduce with the provided StackBlitz (as can be seen by my previous research efforts). The issue gets gradually worse as you have scrolled more, and at some point it just breaks entirely.

@Airblader
Copy link
Contributor

BTW, I somewhat disagree with the P4 label. Drag and drop in a modal is no edge-case, and this is part of the CDK flat-out breaking in its core functionality.

@striky1
Copy link

striky1 commented Jul 2, 2019

Hi here,

I can confirm that it is not working also on:


Angular CLI: 8.0.3
Node: 10.16.0
OS: darwin x64
Angular: 8.0.1

If I was scrolled down on site and then I opened dialog with Drag&Drop two lists, order in them or move item from list to another list is not working. Event of drop function returns same container for previous or current container property, with same indexes.

Can u take a look on that, pls? :)

@DeonduPreez
Copy link

DeonduPreez commented Aug 21, 2019

I ran into the same problem as @striky1 described here, the way I got around this was by scrolling the window to the top before opening the view and scrolling back down by subscribing to the afterClosed event of the modal like below:
const doc = document.documentElement;
const left = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0);
const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);

if (top != 0 || left != 0)
{
  window.scrollTo({
                    top : 0,
                    left: 0
                  });
}

const modal: MatDialogRef = this.dialog.open(ModalComponent);
modal.afterClosed().subscribe(() =>
{
if (top != 0 || left != 0)
{
window.scroll({
top : top,
left : left,
behavior: "smooth"
});
}
});

@endlessxaura
Copy link

endlessxaura commented Sep 18, 2019

Just to weigh in, I'm having this problem as well. For me, it's occurring when the scroll windows for the drag lists are small. I have many different, small drag lists on the modal that items are dragged between. When I scroll down in any of those windows, the ones farther down break in the aforementioned ways.

@mksmtn
Copy link

mksmtn commented Oct 22, 2019

DnD does not work inside MatDialog for me with angular 9. It only drags an item, but dropping the item does not change its order.

@larqitos
Copy link

larqitos commented Nov 1, 2019

@andrewseguin I have the issue as well and occurs when you scroll down on the page and enable a dialog with drag and drop functionality present.

When the dialog is present the cdk-scroll logic modifies the head in the following way:
<html lang="en" class="cdk-global-scrollblock" style="left: 0px; top: -2133px;">

The negative value is calculated based on where the scroll was when the user initiated the dialog box. So that number varies.

Setting the top to 0px or creating a css override with top: 0px solves the problem but does cause the page to scroll in the background. Scrolling is still disabled so this is a bit better solution than the other suggested workaround.

Here is the css to override the negative scroll style
html.cdk-global-scrollblock {
top: 0px !important;
}

If you implement this fix in a global style this will affect all dialog boxes, so I suggest you inject this in a component css class. You may need to leverage ::ng-deep (which I read will eventually go away but it still works in Angular 7)

@larqitos
Copy link

larqitos commented Nov 1, 2019

Digging further into this the drag drop library adds an html element with fixed position to the bottom of the body tag. This is the item that you are actually dragging. This item updates its translate3d value as the user drags the item around.

<div _ngcontent-c34="" cdkdrag="" class="component-box cdk-drag ng-star-inserted cdk-drag-preview" style="touch-action: none; -webkit-user-drag: none; -webkit-tap-highlight-color: transparent; user-select: none; width: 422.188px; height: 46px; transform: translate3d(311px, 655px, 0px); pointer-events: none; position: fixed; top: 0px; left: 0px; z-index: 1000;" dir="ltr"><div _ngcontent-c34="" class="component-title">

The translate3d value needs to be offset with the calculated scroll position of the page. This way the items will take into account the negative scroll implemented by the dialog and should allow drag and drop to work with the dialog.

To confirm this scroll a small amount (around 10pxs) down the page and open the dialog with drag and drop items and if you drag down if you pull down enough you'll see the drag and drop have the offset and react as if the item were higher up when it really is further down.

@sumpton
Copy link

sumpton commented Nov 1, 2019

If there is a way for the Drag and Drop component is inside mat-dialog, it would be helpful to console.log a warning. This is the first time I have used this component and spent too much time wondering where I went wrong, before hunting for bugs and finding this issue.

I can confirm that this works for the first item card in a listing page, but not after scrolling down the page.

Are there plans to fix this, or should developers avoid this component in dialogs?

@ENM1989
Copy link

ENM1989 commented Nov 26, 2019

Same problem here with mat-dialog and drag and drop.

@uvcreation
Copy link

Same problem here, is someone got the solution for this issue?

@larqitos
Copy link

@uvcreation you can take a look at my quick fix here: #15880 (comment)

@uvcreation
Copy link

uvcreation commented Dec 11, 2019

@larqitos It works for me after using ::ng-deep. Thanks mate!

@kotsopoulosd
Copy link

kotsopoulosd commented Dec 20, 2019

Same problem here but derives from different actions. (It has nothing to do with scrolling in my case)

The drag and drop lists are inside matDialog. The first time I open the dialog works fine in Chrome and IE. No matter how many times I open the same matDialog everything works fine.

However if I open another matDialog and then try to open the MatDialog with the drag and drop list, it does not work. The event.container is the same as the event.previousContainer and it does not drop the item neither in the left nor in the right list and vise versa.
The funny thing is that works fine with IE but not with Chrome.

Angular CLI: 8.3.8
Node: 10.16.3
OS: win32 x64
Angular: 8.2.9

@Hydhen
Copy link

Hydhen commented May 12, 2020

I have the same problem, but just with a single dialog, that contains a drag'n'drop directive, the directive works fine within my parent component, but doesn't react to drag inside a dialog
I have no scroll into my parent nor my dialog

@uvcreation
Copy link

I have the same problem, but just with a single dialog, that contains a drag'n'drop directive, the directive works fine within my parent component, but doesn't react to drag inside a dialog
I have no scroll into my parent nor my dialog

try to add this to your component css file

::ng-deep html.cdk-global-scrollblock {
top: 0px !important;
}

@wagnermaciel wagnermaciel added needs triage This issue needs to be triaged by the team and removed needs: clarification The issue does not contain enough information for the team to determine if it is a real bug labels Aug 13, 2020
@crisbeto
Copy link
Member

Duplicate of #14280.

@crisbeto crisbeto removed the needs triage This issue needs to be triaged by the team label Aug 16, 2020
@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 16, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: cdk/drag-drop P4 A relatively minor issue that is not relevant to core functions
Projects
None yet
Development

Successfully merging a pull request may close this issue.