sorting a list by drag & drop breaks when saving to database

Viewed 364

I'm trying to make a list that you can sort by dragging. The frontend part works (javascript only), but as soon as I uncomment component.call('reorder', orderIds); to save the order to the database, it doesn't work anymore. (component.call('reorder', orderIds); is located in the javascript file) I have tried everything I could but I can't get it to work. (examples down below)

I followed this tutorial: https://laravel-livewire.com/screencasts/s8-dragging-list . But he is changing the order of an array but I want to change the order in the database.

Here is my example on codepen to show what I want to achieve: https://codepen.io/MrDexterK/pen/OJpRBWP

Maybe the js is clashing with livewire?

Also look at the console in the following examples
Working example (js only):
https://gyazo.com/9a770e2597143db04e042b670a92b1d3

Not working example (with function uncommented):
https://gyazo.com/17d86a821fc3f686a089c28483a60853

Does anyone know a solution?

Thanks!

The JavaScript

    <script>
        let root = document.querySelector('[drag-root]');

        root.querySelectorAll('[drag-item]').forEach(el => {
            el.addEventListener('dragstart', e => {
                e.target.setAttribute('dragging', true);
            });

            el.addEventListener('drop', e => {
                e.target.classList.remove('bg-yellow-100');

                // get the dragging element
                let draggingEl = root.querySelector('[dragging]');

                // insert it before the drop target
                e.target.before(draggingEl);

                let component = Livewire.find(
                    e.target.closest('[wire\\:id]').getAttribute('wire:id')
                )

                let orderIds = Array.from(root.querySelectorAll('[drag-item]'))
                    .map(itemEl => itemEl.getAttribute('drag-item'))

                console.log('reorder called with: ' + orderIds);

                // when component.call is called it breaks after a few tries
                component.call('reorder', orderIds);
            });

            el.addEventListener('dragenter', e => {
                // e.target.classList.add('bg-yellow-100');

                e.preventDefault();
            });

            el.addEventListener('dragover', e => {
                e.preventDefault();
            });

            el.addEventListener('dragleave', e => {
                // e.target.classList.remove('bg-yellow-100');
            });

            el.addEventListener('dragend', e => {
                e.target.removeAttribute('dragging');
            });
        });
    </script>

The component containing the function that is called

    public function reorder($orderedIds)
    {
        $order = 1;
        foreach ($orderedIds as $orderedId) {
            $question = Question::find($orderedId);
            $question->order = $order;
            $question->save();
            $order++;
        }
    }

Blade file with the draggable items

        <ul drag-root class="overflow-hidden text-indigo-100 font-mono mt-5 w-1/2 flex-inline">
            @foreach($questions as $question)
            <a href="{{ route('admin.questions.edit', ['question' => $question->id]) }}">
                <li drag-item="{{ $question->id }}" draggable="true" class="w-full rounded px-4 pt-1.5 h-10 mt-1 border-2 border-indigo-500 bg-indigo-800 hover:bg-indigo-700 cursor-move">
                    {{ $question->title }}
                </li>
            </a>
            @endforeach
        </ul>

The database table if needed

Database table

0 Answers
Related