'Blazor: Drag & Drop list elements

I would like to know how to bind Drag & Drop events to rearrange items in a list.

This is the code I have:

<PageTitle>Drag & Drop</PageTitle>

<ul style="border:1px solid black">
    @foreach (var item in Items)
    {
        <li draggable="true" @* draggable *@
            @[email protected]
            id="@item.Id"              
            @* how to bind drag events? *@
        >@item.Label</li>
    }
</ul>

@code {
    public class Item
    {
        public int Id {get; set;}
        public string Label {get; set; } = default!;
    }
    public List<Item> Items = new() {
        new Item(){Id= 1, Label = "hi 1"},
        new Item(){Id= 2, Label = "hi 2"},
        new Item(){Id= 3, Label = "hi 3"},
        new Item(){Id= 4, Label = "Move me!"},
    };

}


Solution 1:[1]

Here I illustrate some basic Drag & Drop html5 event handling operations just with Blazor:

enter image description here

Here is the code, self explanatory.

@page "/"

<PageTitle>Drag & Drop Sample</PageTitle>

<ul style="border:1px solid black">
    @foreach (var item in Items)
    {
        <li draggable="true"
            class="@(DragEnter==item?"inserting":"")"
            @[email protected]
            id="@item.Id"              
            ondragover="event.preventDefault();"
            @ondragstart="@( (e) => hondragstart(e, item))"
            @ondrop="@( () => hondropOverAFriend(item))"
            @ondragenter="@( ()=> hondragenter(item) )"
            @ondragend="@( ()=> hondragend() )"
        >@item.Label</li>
    }
    <div style="height: 1.5em;" 
        ondragover="event.preventDefault();"
        @ondrop="hondropBotton"
        @ondragenter="hondragenterBotton"
    />
</ul>

<style>
    .inserting
    {
        border-top: 1px solid black;
        margin-top: 5px;
    }
</style>

@code {
    public class Item
    {
        public int Id {get; set;}
        public string Label {get; set; } = default!;
    }
    public List<Item> Items = new() {
        new Item(){Id= 1, Label = "hi 1"},
        new Item(){Id= 2, Label = "hi 2"},
        new Item(){Id= 3, Label = "hi 3"},
        new Item(){Id= 4, Label = "Move me!"},
    };
    public void  hondropOverAFriend(Item friend)
    {
        DragEnter=null;
        if (DraggedItem == null) return;
        if (DraggedItem == friend) return;
        var friendposition = Items.IndexOf(friend);
        Items.Insert(friendposition, DraggedItem!);
        DraggedItem=null;
    }
    public void  hondropBotton()
    {
        DragEnter=null;
        if (DraggedItem == null) return;
        Items.Add(DraggedItem!);
        DraggedItem=null;
    }
    public void  hondragstart(DragEventArgs e, Item item)
    {
        e.DataTransfer.EffectAllowed = "move"; //does't run
        DraggedItem = item;
        DraggedItemPosition = Items.IndexOf(item);
        Items.Remove(DraggedItem!);
    }    
    public void  hondragenter(Item item)
        =>
        DragEnter = item;    
    public void  hondragenterBotton()
        =>
        DragEnter = null;
    public void  hondragend()
    {
        // never fired IDK why
        if (DraggedItem == null) return;        
        DragEnter = null;
        Items.Insert(DraggedItemPosition, DraggedItem!);        
    }
    private Item? DraggedItem;
    private int DraggedItemPosition;
    private Item? DragEnter;
}

Disclaimer

They are some things that I don't know how to do without JSInterop, for example, I was unable to change EffectAllowed or to set data on DataTransfer. People, be free to improve code!

Solution 2:[2]

If you change @ondragend="@(()=> hondragend())" to @ondragend="hondragend" It will fire the event on your code

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 user3275015