wotzebra / livewire-sortablejs

A Laravel Livewire plugin that makes it easy to use Sortable.js
MIT License
289 stars 25 forks source link

Livewire V3 morph markers are not handled correctly #31

Closed chillbram closed 1 year ago

chillbram commented 1 year ago

Livewire's new automatic morph markers <!-- __BLOCK__ --> and <!-- __ENDBLOCK__ --> are used to determine how Livewire handles DOM updates with various Blade operators like @if() and @foreach. The most common use case for Sortable is inside a @foreach/@forelse. This still works, apart from when an item is moved to the last position in the sortable group.

When a sortable item is moved to the last position it is placed below the <!-- __ENDBLOCK__ --> marker, while it should be above the marker and below the now second to last item.

If the item only contains regular data (e.g. text), this resolves itself as Livewire will just create a new element within the block and delete the element that is now outside of it. However, if the items contain Livewire components these get detached and Livewire will complain that it is missing the Livewire component snapshot. This problem also arises for anything that would be attached to these elements, like event listeners.

The following code is a minimal LW class to replicate this bug:


namespace App\Livewire;

use Livewire\Component;

class MorphMarkerBug extends Component
{
    public $items = [['order' => 1, 'value' => 1], ['order' => 2, 'value' => 2], ['order' => 3, 'value' => 3]];

    public function updateOrder($order)
    {
        $this->items = $order;
    }

    public function render()
    {
        return <<<'BLADE'
<div wire:sortable="updateOrder">
    @foreach($items as $item)
        <div wire:sortable.item="{{ $item['value'] }}" wire:key="item-{{ $item['value'] }}">
            <span>{{ $item['value'] }}</span>
        </div>
    @endforeach
</div>
BLADE;
    }
}

https://github.com/nextapps-be/livewire-sortablejs/assets/7299762/b5ac6e55-42ca-4ef3-96fe-e470fde95743

gdebrauwer commented 1 year ago

This seems to be caused Sortablejs itself, so I am not sure if we will be able to fix/prevent this issue 🤔