Postlagerkarte/blazor-dragdrop

Nested DropZones

Opened this issue · 5 comments

Hi,

I noticed the change in March to allow nested dropzones but I don't seem to be able to get this working.

It's a bit hard to give you some example code but essentially it is a page that has loads several components and within the component it can contain a dropzone containing instances of itself recursively. So you can tell I end up with dropzones within dropzones.

I'm using event callbacks to handle the ondropped event on the top level page but whilst I get the event fired from the top level drop zone I don;;t get it fired from the sub level drop zones.

I hope that makes sense, am I doing something wrong? What other information might you need from me?

Thanks,

Paul.

Hi there, can you provide a minimal reproducible example?

Hi there, can you provide a minimal reproducible example?

Hi, I've created a quick project with an example of the issue here:

The test page has the instructions for you to try that show you a working drag and drop and the ones that don't work.

Let me know if you need any explanation of anything.

Many thanks,

Paul.

The test project is too complex for my taste so I reduced it as much as possible to:

<PageComponent>
    <Dropzone Items="tree.Children" InstantReplace="false" TItem="Tree" Accepts="AcceptedItem" OnItemDrop="@OnDropped">
        @if (context.Type == Model.ITEM_TYPES.SECTION)
        {
            <SectionComponent Level="1" Tree="context"></SectionComponent>

            <Dropzone Items="context.Children" InstantReplace="false" TItem="Tree" Accepts="AcceptedItem" OnItemDrop="@OnDropped">
                <ChildContent Context="context2">
                    @if (context2.Type == Model.ITEM_TYPES.CATEGORY)
                    {
                        <CategoryComponent Level="2" Tree="context2"></CategoryComponent>

                        <Dropzone Items="context2.Children" InstantReplace="false" TItem="Tree" Accepts="AcceptedItem" OnItemDrop="@OnDropped">
                            <ChildContent Context="context3">
                                @if (context3.Type == Model.ITEM_TYPES.TEXTSINGLE)
                                {
                                    <TextSingleComponent Level="3" Tree="context3"></TextSingleComponent>
                                }
                            </ChildContent>
                        </Dropzone>
                    }
                </ChildContent>
            </Dropzone>
        }
    </Dropzone>
</PageComponent>

As we can see, you are nesting 3 levels. With 2 levels it seems to work though.

Basically the most prominent underlying issue here is #99 which is not resolved yet. See the comments there.

But there are also other issues like:

  • wild use of cascading values, you should avoid this approach as it overcomplicates things and is bad for performance, replace it by simple parameters
  • calling ToList() in ItemComponent to pass the items to the DropZone which creates a new list on each render cycle, comparing item instances won't work, jut use IList everywhere as DropZone and its services rely on it
  • missing assignment of Accepts handlers for recursive calls to ItemComponent in ItemComponent

Also I recommend to clone the sources of this project and use a project reference to these sources in your project to allow debugging of the DropZone and its services.

Thank you for your quick reply, I'll give it a go tomorrow.

I have done a small trick.
In the first div after dropzone I gave style "pointer-events: all" and in an inner div "pointer-events: none"
`

    <div style="pointer-events: all;">
        <div style="pointer-events: none">
           navigationDto.Title
        </div>
    </div>
        <MenuComponent @key=navigationDto.Navigations Level="@(Level+1)" Navigations="@navigationDto.Navigations" OnDropped="OnDropped" AcceptedItem="AcceptedItem"></MenuComponent>
`