Insert a new section/component on drag and drop with Blazor

Viewed 734

I am trying to make a new section/div/component to appear in the droparea upon the drop action.

enter image description here

For example, I make two blazor components <Calculator/> and <Counter /> which should be put in a dropzone's div depending on which one was dragged. So far I have two draggable elements:

@page "/"
<!-- draggable items-->
<ul>
    <li draggable="true" @ondragstart="OnDragStart">drag Counter</li>
    <li draggable="true" @ondragstart="OnDragStart">drag Calculator</li>
...
</ul>

Then I have multiple divs and among them dropzone divs. Depending in which zone I drop it, there the new component should be rendered:

<!-- drop zones-->
<div class="bg-primary">
    <div class="row one">Test</div>
    <div dropzone="move" class="row space" 
         @ondrop="OnDrop" ondragover="event.preventDefault();"></div>
    <div class="row two"></div>
    <div dropzone="move1" class="row space" 
         @ondrop="OnDrop" ondragover="event.preventDefault();"></div>
    <div class="row three">Test</div>
</div>

My code is not doing much yet, only indicating what action is taking place:

<div>@DragStatus</div>

@code {
    public string DragStatus = "test...";

    public void OnDragStart()
    {
        DragStatus = "started";
    }
    public void OnDrop()
    {
        DragStatus = "dropped";  
    }
}

How would I indicate which of two elements was taken/dragged?

1 Answers

I have found a solution. It is more functional than professional. Just to give an idea.

On drag start event you can pass a variable of what is being dragged to a function:

<li draggable="true" @ondragstart='(() => OnDragStart("Counter"))'>drag Counter</li>
<li draggable="true" @ondragstart='(() => OnDragStart("Calculator"))'>drag Calculator</li>

Then we need to know where this item is being dropped:

<div dropzone="move1" class="row space" 
@ondrop='(() => OnDrop("first"))' ondragover="event.preventDefault();">B</div>
<div class="row two"></div>

From above we get two values {first, calculator} so it can be stored into tuple:

    public List<Tuple<string, string>> myitems { get; set; }
    = new List<Tuple<string, string>>();
    public string place { get; set; } = "";
    public string DragStatus = "test...";

Two functions will save this data only when an item is both dragged and dropped:

    public void OnDragStart(string taken_a)
    {
        DragStatus = taken_a; //what is being dragged

    }
    public void OnDrop(string place_a)
    {
        place = place_a;
        var item = new Tuple<string, string>(place, DragStatus);
        myitems.Add(item);
    }

Finally we can loop through a list of tuples inside dropzone div:

    <div dropzone="move1" class="row space"
         @ondrop='(() => OnDrop("first"))' ondragover="event.preventDefault();">

        @foreach (var item in myitems)
        {
            @if (item.Item1 == "first")
            {
                @if (item.Item2 == "Calculator")
                {
                    <Calculator />
                }
                @if (item.Item2 == "Counter")
                {
                    <Counter />
                }
            }
        }
    </div>

It may work for some small data sets, because you need to put such loops under each dropzone.

Otherwise, one of the professional methods seems to be render trees. A good resource on it: https://chrissainty.com/building-components-via-rendertreebuilder/

Related