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

[cdk drag drop] restrict possible insert positions for a drag into a dropList #18673

Open
ataraciuk opened this issue Mar 2, 2020 · 9 comments
Labels
area: cdk/drag-drop feature This issue represents a new feature or feature request rather than a bug or bug fix P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects

Comments

@ataraciuk
Copy link

Feature Description

I would like to be able to somehow limit at what positions a drag element can be dropped into a dropList. I couldn't find any way of doing that with the current API.

Ideally, if let's say a drag can only be dropped into position 3 or bigger, and it's begin dragged over position 1, the drop would still allowed, but the placeholder would show position 3, and drop event would occur over position 3, and not 1.

I'm considering using a combination of CdkDragEnter and CdkDragMove to style the placehoder for invalid positions and then the drop event to cancel an invalid move, but maybe there's a better way of doing that? Any advice will be appreciated.

I also considered using multiple droplists, but I need the whole area to be droppable, and with the long term goal of showing the placeholder on the previous valid index (as opposed to not showing a placeholder and not allowing the drop), a single dropList sounds a better approach.

Thank you.

Use Case

For a dropList with 10 elements, a drag element can only be dropped between positions 3 and 7. Dragging over positions 1 and 2 shows the placeholder element on position 3, and drop event has position parameter set as 3. As a less desirable but still happy outcome, when dragging over positions 1 or 2 a placeholder is not shown, and the dropList does not fire the drop event when dropping there, as if the move were invalid.

@ataraciuk ataraciuk added the feature This issue represents a new feature or feature request rather than a bug or bug fix label Mar 2, 2020
@crisbeto
Copy link
Member

crisbeto commented Mar 2, 2020

Seems reasonable. What behavior would you expect in this case? Try to find the closest non-restricted position in the list and insert it there?

@ataraciuk
Copy link
Author

Thank you for the answer.
The behavior on drop has to match the behavior on what/where/if we show the drop placeholder while dragging.

Ideally, as you said, inserting on the closest non-restricted. But it seems harder to do.

The difficulty for the onDrop logic doesn't seem much harder to find the closest non-restricted index vs. not allowing the drop, and it's something I can currently do without much trouble I believe ((cdkDropListDropped) event has position, I have my range of allowed indexes).

The biggest difficulty seems to be the display of the placeholder. With current implementation, I think I can do hiding it for non-valid indexes, assuming I can dynamically style the placeholder, by listening to CdkDragEnter and CdkDragDrop and then altering the placeholder style/dom. This would work for the solution where I don't want to allow dropping outside the valid indexes. I don't think there's a way right now to show the placeholder on the closest valid index.

If the library would have an @input for valid indexes (thinking a function similar to cdkDropListEnterPredicate, but returning number[]), or a startIndex and endIndex inputs (if a range makes it easier than any combination of indexes, that works too!), that would solve all my troubles :D but failing that, any insight on the best approach to achieve this with the current api is very welcome.

Thanks!

@Achilles1515
Copy link

@ataraciuk This would be a cool feature, but there are still more questions and complexity to address, especially around the functionality of list sorting with these boundaries in place. For example, if you can only drop an item between [2, 4], I'm assuming you don't want to be able to sort the list and have it go out of that range? Then what happens if all the items between [2,4] in my list do have a range boundary of [2,4], then I drag another item between [2,4]. Obviously, those existing [2,4] elements wouldn't want to be sorted out of that range. So idk, there's a lot to think about.

Fwiw, you can probably hack your way into a solution by overriding private methods. Here is an example I quickly cooked up with a [2, 4] range (global range and not per drag item). My edits are at the bottom (see "// EDIT: ..." comments, I also forked this from the official 'disabled sorting' example, but re-enabled sorting). Ignoring private method overriding, this is obviously not a complete solution for what you are looking for, but just a beginning proof-of-concept.

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

@ataraciuk
Copy link
Author

ataraciuk commented Mar 4, 2020

@Achilles1515 thanks a lot for your input and your code example! very helpful

I'm not thinking a global/static range limit, but more on a per drag case. Maybe something analog to cdkDropListEnterPredicate, but instead of saying 'can this item be entered into this list', saying 'can this item be entered at this position on this list', and if not, showing it on the closest allowed one. After the item is dropped, the restriction is forgotten until a new drag.

But I totally get your points.

For context: All this comes from a product request of having our list first ordered by some status, and then by the user-decided position. Which kind of clashes with the idea of a drag and drop list (the position being tied to the cursor position). I'm trying to give the best solution to the product team that is feasible and not too hacky (maintainable). Ideally, the user could drag an element in any point of the list, but if dragging around items with a different status than the item that is being dragged, we want to show where it would be positioned when dropped (either the first or last position on the items of that status, depending if dragging too far to the left or right), which breaks the assumption of cursor position == drop position. As a probably accepted solution but not as good, if dragging over items with different status, we don't allow the drop (and we wouldn't show any placeholder).

I will try to convince the designer with a solution where we allow to drag and drop everywhere and show a tooltip/warning that the item will be reordered to be in its matching status.

First I considered a solution with one droplist next to each other per each status, but it's important to have the whole area droppable when no items at all (or only items of same status).

I hope this helps understanding what Im trying the achieve.

Thanks,

@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 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 May 26, 2020
@crisbeto crisbeto added this to Triaged in triage #1 via automation May 26, 2020
@jpike88
Copy link

jpike88 commented Jul 22, 2020

I've just hit this wall too.

It doesn't make sense to selectively restrict indexes for drops if ordering is kicking in and scrambling indexes, it could maybe even result in an infinite loop. I think the solution would be to only allow this on an unsorted list because that's the only scenario where you can guarantee deterministic behavior. If sorting really needs to occur on a drop, that can be done post-drop by the developer.

@jpike88
Copy link

jpike88 commented Jul 22, 2020

@Achilles1515 thanks from your code sample, looks like it works great for now

@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.

@jhaynes32
Copy link

@angular-robot this should definitely be a feature. I need to keep the order of the elements and only add to the end of a list.

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 P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects
No open projects
triage #1
  
Triaged
Development

No branches or pull requests

7 participants