wotzebra / livewire-sortablejs

A Laravel Livewire plugin that makes it easy to use Sortable.js
MIT License
286 stars 24 forks source link
laravel laravel-livewire livewire sortable sortablejs

Livewire Sortable.js

Latest Version on NPM NPM total downloads NPM downloads per month

A plugin/wrapper around Sortable.js package.

Why use this instead of Livewire's official livewire-sortable package?

The livewire-sortable package uses Shopify's sortable package. We noticed some issues with that package compared to Sortable.js:

Do you want to make the switch from livewire-sortable to livewire-sortable.js? That's easy, because this package works exactly the same! The only difference is the javascript package it uses in the background. You will not have to change any Livewire attributes or methods!

Installation

CDN

<script src="https://unpkg.com/@wotz/livewire-sortablejs@1.0.0/dist/livewire-sortable.js"></script>

NPM

npm install @wotz/livewire-sortablejs --save-dev

Import the package in your bundle:

import '@wotz/livewire-sortablejs';

// or

require('@wotz/livewire-sortablejs');

Usage

One group with draggable items

When you only have one list of draggable items (e.g. to-do list), you have to add the following attributes to your html:

<ul wire:sortable="updateTaskOrder" wire:sortable.options="{ animation: 100 }">
    @foreach ($tasks as $task)
        <li wire:sortable.item="{{ $task->id }}" wire:key="task-{{ $task->id }}">
            <h4>{{ $task->title }}</h4>
            <button wire:sortable.handle>drag</button>
        </li>
    @endforeach
</ul>

When the order is updated, you will receive the following array structure in your Livewire method:

[
    [
        'order' => 1,   // order of item (starts at 1, not 0)
        'value' => 20,  // item id
    ],
]

Multiple groups with draggable items

When you have multiple lists, each with items that can be moved between those different lists, you have to add the following attributes to your html:

<div wire:sortable-group="updateTaskOrder">
    @foreach ($groups as $group)
        <div wire:key="group-{{ $group->id }}">
            <h4>{{ $group->label }}</h4>

            <ul wire:sortable-group.item-group="{{ $group->id }}" wire:sortable-group.options="{ animation: 100 }">
                @foreach ($group->tasks()->orderBy('order')->get() as $task)
                    <li wire:sortable-group.item="{{ $task->id }}" wire:key="task-{{ $task->id }}">
                        <span>{{ $task->title }}</span>
                        <button wire:sortable-group.handle>drag</button>
                    </li>
                @endforeach
            </ul>
        </div>
    @endforeach
</div>

When an item is dragged, you will receive the following array structure in the Livewire method you provided to the wire:sortable-group directive (in this example, the updateTaskOrder method):

[
    [
        'order' => 1,            // order of group (starts at 1, not 0)
        'value' => 20,           // group id
        'items' => [
            [
                'order' => 1,    // order of item within group (starts at 1, not 0)
                'value' => 50,   // item id
            ]
        ]
    ]
]

Multiple draggable groups with draggable items

When you have multiple lists, each with items that can be moved between those different lists and the lists themselves also need to be draggable, you have to add the following attributes to your html:

<div wire:sortable="updateGroupOrder" wire:sortable-group="updateTaskOrder" wire:sortable.options="{ animation: 50 }">
    @foreach ($groups as $group)
        <div wire:sortable.item="{{ $group->id }}" wire:key="group-{{ $group->id }}">
            <h4>{{ $group->label }}</h4>
            <button wire:sortable.handle>drag group</button>

            <ul wire:sortable-group.item-group="{{ $group->id }}" wire:sortable-group.options="{ animation: 100 }">
                @foreach ($group->tasks()->orderBy('order')->get() as $task)
                    <li wire:sortable-group.item="{{ $task->id }}" wire:key="task-{{ $task->id }}">
                        <span>{{ $task->title }}</span>
                        <button wire:sortable-group.handle>drag item</button>
                    </li>
                @endforeach
            </ul>
        </div>
    @endforeach
</div>

When an item is dragged, you will receive the following array structure in the Livewire method you provided to the wire:sortable-group directive (in this example, the updateTaskOrder method):

[
    [
        'order' => 1,            // order of group (starts at 1, not 0)
        'value' => 20,           // group id
        'items' => [
            [
                'order' => 1,    // order of item within group (starts at 1, not 0)
                'value' => 50,   // item id
            ]
        ]
    ]
]

When a group is dragged, you will receive the following array structure in the Livewire method you provided to the wire:sortable directive (in this example, the updateGroupOrder method):

[
    [
        'order' => 1,            // order of group (starts at 1, not 0)
        'value' => 20,           // group id
    ]
]

Building

npm run build

Changelog

Please see CHANGELOG for more information what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Credits

This package is inspired by Livewire's official livewire-sortable plugin.

License

The MIT License (MIT). Please see License File for more information.