draggable: [BUG] Incorrect oldIndex when there are nested draggable containers
I’m using the library to build a layout creator.
There is a main Sortable container which contains draggable items. Some of these draggable items can themselves contain a nested Sortable container.
When I drag an item from the main Sortable container and drop it into a nested Sortable container, I’m getting an incorrect value for oldIndex. This happens only if I’m dragging an item which is located after the nested Sortable container in the DOM.
______________________________________________________________________________________________
| Main Sortable |
| ___________________________________________________________________________________ |
| | Draggable item A (direct child to main Sortable) | |
| | _________________________________________________________________________ | |
| | | Nested Sortable | | |
| | | ________________________________________________________________ | | |
| | | | Nested Draggable item B | | | |
| | | |_______________________________________________________________| | | |
| | |_________________________________________________________________________| | |
| |___________________________________________________________________________________| |
| |
| ___________________________________________________________________________________ |
| | Draggable item C (direct child to main Sortable) | |
| |___________________________________________________________________________________| |
|_____________________________________________________________________________________________|
When I drag Draggable item C
into Nested Sortable
just next to Nested Draggable item B
, the value of oldIndex for Draggable item C
is 2, instead of 1.
I’m expecting 1 because inside Main Sortable
, Draggable item C
is the second child and should have 1
as its index.
I found the issue at this line in Draggable.js
getDraggableElementsForContainer(container) {
> const allDraggableElements = container.querySelectorAll(this.options.draggable);
return [...allDraggableElements].filter((childElement) => {
return childElement !== this.originalSource && childElement !== this.mirror;
});
}
We are querying ALL draggable items inside the container of Draggable item C
, which includes the nested draggable items too. This makes the oldIndex for Draggable item C
much higher than expected.
A quick fix could be to update the getDraggableElementsForContainer()
function to this:
getDraggableElementsForContainer(container) {
const allDraggableElements = container.querySelectorAll(this.options.draggable);
return [...allDraggableElements].filter((childElement) => {
> return childElement !== this.originalSource && childElement !== this.mirror && childElement.parentNode === container;
});
}
I’m returning only the direct children of the parent by using childElement.parentNode === container
.
Please let me know if it makes sense to file a pull request including this fix. I’d love to contribute, even though it’s a tiny contribution 😃
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 2
- Comments: 17 (17 by maintainers)
I have created a PR with the changes that we discussed. As for the test suite, I just updated the same Codepen. Since only the Sortable.js file is changed, I thought the same Codepen with updated sortable.js would do.
This fix works very well.
I’m glad I was able to help make this great library better. 😃
And yeah, I agree that we should create a new method instead of updating the existing one. I’ll create the PR and the tests after a bit. Hopefully it gets merged for the next release.
Emm… I think we shouldn’t change
getDraggableElementsForContainer
but add agetSortableElementsForContainer
method in sortable.Maybe because of network problems I got
Refused to execute script from 'https://srv-file4.gofile.io/download/RFpGbt/draggable.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
error when opened https://codepen.io/davidaik/pen/gOrpeMO . There are tests based on the discussion above https://github.com/zjffun/draggable/commit/f2e020d7f2c8c7965ec2f6cf378551716c17724a. It works fine exceptFailed to execute 'insertBefore' on 'Node'
error.I’ll be happy to look into that error message. I’ll update here if I manage to come up with a solution.
Thank you so much, I will check it tonight 🎉
Hmm… I found a somewhat rare occasion where the error was still showing. I think updating the
moveWithinContainer
function in Sortable.js at line 276 from this:To this:
is better.
Please confirm that it works for you too 😃
Hi,
Sorry for late response, It worked but we still have some problems that need to be resolved (the errors logged on console), please see image below.
I think your fix can be merged with some test cases but it still can’t be released until we find out the error. Currently, I have an urgent deadline so I can’t fix it soon, maybe a few weeks later 😢
May you help to fix this error? It will be our pleasure.
BTW, Hi @zjffun , sorry for bothering you, just to says that if you have rest time, may you help to check this issue? I really appreciate your help
Thank you so much 😄
@bahung1221 Here is a Codepen with a working nested sortable. It has the fix applied, so the value of oldIndex is correct. https://codepen.io/davidaik/pen/gOrpeMO