blazorbootstrap icon indicating copy to clipboard operation
blazorbootstrap copied to clipboard

Sortable list doesn't allow click and drag/scroll with MAUI Blazor.

Open josephroy99 opened this issue 1 year ago • 9 comments

Describe the bug When using MAUI Blazor, and implementing the scrollable list, it is not possible to drag any of the elements.

To Reproduce Steps to reproduce the behavior:

  1. Set up the project as per the getting started documentation.
  2. Make sure to include the sortable.js reference in the index.html file.
  3. Copy the code section for a simple sortable list into the home page
  4. Run and click and drag on an element.
  5. The dragging doesn't move the element that was clicked/pressed.

Expected behavior The element that was dragged should follow the mouse.

Screenshots N/A

Versions (please complete the following information):

  • .NET Version: .NET 8
  • BlazorBootstrap: 3.0.0
  • Blazor WebAssembly / Server: MAUI Blazor
  • Blazor Interactive Render Mode: MAUI Blazor
  • Blazor Interactivity Location: Per Pagew Component

Sample code

@page "/"

<SortableList Class="mb-3"
              Handle=".bb-sortable-list-handle"
              TItem="Employee"
              Data="employees"
              Context="item"
              OnUpdate="@OnEmployeeListUpdate">

    <ItemTemplate>
        <div class="d-flex justify-content-start">
            <div class="bb-sortable-list-handle pe-2"><Icon Name="IconName.GripVertical" /></div>
            <div>@item.Name</div>
        </div>
    </ItemTemplate>

</SortableList>

@code {
    public List<Employee> employees = Enumerable.Range(1, 5).Select(i => new Employee(i, $"Employee {i}")).ToList();

    private void OnEmployeeListUpdate(SortableListEventArgs args)
    {
        var itemToMove = employees[args.OldIndex];

        employees.RemoveAt(args.OldIndex);

        if (args.NewIndex < employees.Count)
            employees.Insert(args.NewIndex, itemToMove);
        else
            employees.Add(itemToMove);
    }

    public record Employee(int Id, string? Name);
}

Desktop (please complete the following information):

  • Device: x86 PC
  • OS: Windows 11
  • Browser: Blazor Web View (Edge?)
  • Version: ?

josephroy99 avatar Sep 27 '24 12:09 josephroy99

To add context, this code was copied from the handle demo, but the code example for the basic demo with no handle also doesn't work.

josephroy99 avatar Sep 27 '24 13:09 josephroy99

I have the same issue. With Blazor Web App it works fine but in the MAUI blazor there is no functionality.

cs-mq avatar Sep 30 '24 20:09 cs-mq

Can anyone provide a statement on whether it is likely that this issue will be resolved in MAUI hybrid in the short term? I would appreciate feedback so that I can plan whether I need to implement a different drag-and-drop function for my lists.

cs-mq avatar Oct 01 '24 10:10 cs-mq

@josephroy99 @cs-mq Thank you for using BlazorBootstrap. Will check and get back to you on this?

gvreddy04 avatar Oct 01 '24 16:10 gvreddy04

Can anyone already provide feedback on whether this bug will be fixed in the foreseeable future?

cs-mq avatar Oct 08 '24 13:10 cs-mq

I am now experiencing the same using blazor bootstrap

collinsmarra avatar Apr 07 '25 19:04 collinsmarra

Hello everyone, unfortunately I have to record the same behavior. The only reaction I receive when clicking on an element, before an error is generated, is the display of the icon shown in the figure:

Image

MaMon1963 avatar Apr 16 '25 20:04 MaMon1963

In my example, where I tried to add drag-and-drop sortable rows in the Grid component, I encountered the same issue. The solution was to store the Sortable object in a global variable and destroy/recreate it every time the code runs:

let sortableInstance;

window.initItemsOrderedGrid = (dotNetRef) => {   
      ....
      if (sortableInstance) {
          sortableInstance.destroy(); // required for MAUI
      }
      ....
}

Also, in the C# code, I had to re-initialize the JS script each time the Grid was updated:

await itemsGrid.RefreshDataAsync();
// Re-initialize the JS component (workaround for MAUI)
await JS.InvokeVoidAsync("initItemsOrderedGrid", _dotNetRef);

Maybe it's the same case with the Sortable List component?

stormenergy91 avatar Jul 14 '25 21:07 stormenergy91

Update this file blazor.bootstrap.sortable-list.js in this way and wrorks perfect on Maui:

let sortableInstance;
export function initialize(elementId, elementName, handle, group, allowSorting, pull, put, filter, dotNetHelper) {
    let listGroupEl = document.getElementById(elementId);
    if (listGroupEl == null)
        return;

    if (Sortable) {

        if (sortableInstance) {
            sortableInstance.destroy();
        }

        sortableInstance = Sortable.create(listGroupEl, {
            animation: 150,
            fallbackOnBody: true,
            swapThreshold: 0.65,
            touchStartThreshold: 5,
            fallbackTolerance: 3,
            forceFallback: true,
            ghostClass: "sortable-ghost",
            filter: '.bb-sortable-list-item-disabled',
            group: {
                name: group,
                pull: pull,
                put: put
            },
            handle: handle, // handle's class
            onAdd: (event) => {
                event.item.remove();
                dotNetHelper.invokeMethodAsync('OnAddJS', event.oldDraggableIndex, event.newDraggableIndex);
            },
            onRemove: (event) => {

                if (event.pullMode === 'clone') {
                    event.clone.remove();
                }

                event.item.remove();
                event.from.insertBefore(event.item, event.from.childNodes[event.oldIndex]);

                let fromElName = '';
                let toElName = '';

                let fromEl = document.getElementById(event.from.id);
                if (fromEl)
                    fromElName = fromEl.getAttribute('name');

                let toEl = document.getElementById(event.to.id);
                if (toEl)
                    toElName = toEl.getAttribute('name');

                dotNetHelper.invokeMethodAsync('OnRemoveJS', event.oldDraggableIndex, event.newDraggableIndex, fromElName, toElName);
            },
            onUpdate: (event) => {
                event.item.remove();
                event.to.insertBefore(event.item, event.to.childNodes[event.oldIndex]);
                dotNetHelper.invokeMethodAsync('OnUpdateJS', event.oldDraggableIndex, event.newDraggableIndex);
            },
            sort: allowSorting
        });
    }
}

stormenergy91 avatar Jul 15 '25 10:07 stormenergy91