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

bug(drag-drop): cdkDropListSortingDisabled interacts badly with connected lists #23766

Open
thw0rted opened this issue Oct 15, 2021 · 4 comments
Labels
area: cdk/drag-drop P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent

Comments

@thw0rted
Copy link

Reproduction

This is a fork of the "disable sorting" example from the docs.

https://stackblitz.com/edit/angular-lcgpvd?file=src/app/cdk-drag-drop-disabled-sorting-example.ts

Steps to reproduce:

  1. Open example
  2. Drag an item from one list to another

Expected Behavior

One of the following, internally-consistent behaviors:

  • the receiving list provides some way of determining where the incoming item will be sorted
  • the incoming item always goes before the first item
  • the incoming item always goes after the last item

Actual Behavior

The incoming item gets a placeholder wherever the user drags it, but then can't be moved. The user can continue dragging back to the original list, so the placeholder goes back to the original position then drag over the target list again to put the placeholder in a new position -- but again, can't move the placeholder directly.

Environment

  • Angular: 12.2.9
  • CDK/Material: 12.2.9
  • Browser(s): Chrome
  • Operating System (e.g. Windows, macOS, Ubuntu): Win10

Comments

I'd like to see the first behavior implemented -- let me supply a sort-function that gets the dragged item's data (and maybe the index in its current container?) as an input and outputs the list index at which the placeholder should be inserted. Failing that, I'd at least like a property that lets me say that, since sorting is disabled, the placeholder should go at the "start" or "end".

@thw0rted thw0rted added the needs triage This issue needs to be triaged by the team label Oct 15, 2021
@crisbeto
Copy link
Member

The logic of where to place the item when sorting is disabled is:

  1. Check if it's the container from which dragging started. If it is, use the initial index.
  2. Place the item based on the place in which it entered the container.

We have the cdkDropListSortPredicate input which allows you to customize the sorting logic. Have you tried using it?

@thw0rted
Copy link
Author

Thanks for looking at this. I updated my example code to try to use cdkDropListSortPredicate, but it's having a few issues.

First, the predicate is being called with this set to the CdkDropList component on which it's a property, instead of the host component (CdkDragDropDisabledSortingExample). Is this a common pattern for predicates/callbacks passed to components? I thought that callbacks like nameFor were invoked with the host as context. I don't see an obvious way to get a handle on the host when the method is called, hence my (very) hacky workaround passing the host-component instance via module-level variable.

Second, it doesn't seem to work all the time. Take a look at the updated example. The top list's predicate returns true only for index=0 (so, dragging in to the top of the list) -- drag into any spot but the top and the item goes to the bottom, which seems consistent enough. The bottom list's predicate always returns false, so you'd think that would make the item always enter at the bottom, but it's somehow still possible to enter at the top. It behaves the same way as the predicate that returns true for index zero. There doesn't appear to be any way to use the predicate to force the item to enter at a particular point, i.e., always first or always last.

@crisbeto
Copy link
Member

Regarding the first question, unfortunately we don't have access to the origin context so it's difficult to solve on our end. You should be able to fix it by defining the predicate as an arrow function: public predicate = () => {...}.

Regarding the second question, it's not something I was thinking about when I added the predicate so it could be a bug. Also you might want to check out the cdkDropListEnterPredicate which will prevent an item from entering a list based on a custom condition.

Also one more note: you don't really need to disable sorting if you're using the predicate input.

@thw0rted
Copy link
Author

OK, so, if the sort predicate is able to force an item to be inserted at the end, only, at least that would be consistent, but we still have no control over where the item is inserted, because we don't have a say in where it winds up when the predicate returns false. I agree that at least fixing the bug so it can't be inserted at the beginning would be an improvement. It would be nice to have, if I could tell it where a "sort rejected" item will enter the list.

@crisbeto crisbeto added area: cdk/drag-drop P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent and removed needs triage This issue needs to be triaged by the team labels Oct 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: cdk/drag-drop P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects
None yet
Development

No branches or pull requests

3 participants
@thw0rted @crisbeto and others