Livewire Sortable

repository·master·Indexed 19 days ago

https://github.com/livewire/sortable

A plugin for Livewire applications that provides a wrapper around Shopify's draggable/sortable logic to implement drag-and-drop sorting interfaces. It supports simple flat lists using the wire:sortable directive and complex nested groups (Trello-style) using the wire:sortable-group directive. Version 1.0.0 supports Livewire v3.

Tokens
2.4K
Snippets
6
Records
7
Agent score
19%

What's inside livewire-sortable

  1. Install Livewire Sortable via NPM

    master

    Install the package using npm as a dev dependency:

    npm install livewire-sortable --save-dev

    Then, import it into your JavaScript bundle using either import or require syntax.

    import 'livewire-sortable'
    // Or.
    require('livewire-sortable')
  2. Install Livewire Sortable via CDN

    master

    To use Livewire Sortable via a CDN, include the following script tag in your HTML.

    Note: This package (v1.x.x) only supports Livewire v3. If you are using Livewire v2, you must use version 0.3.0.

    <script src="https://cdn.jsdelivr.net/gh/livewire/sortable@v1.x.x/dist/livewire-sortable.js"></script>
  3. Implement nested sortable groups (Trello-style)

    master

    To create complex layouts with draggable groups containing draggable items, use the following attributes:

    For the Group Container:

    • wire:sortable="methodName": The method called when groups are reordered.
    • wire:sortable-group="methodName": The method called when items are reordered within or between groups.

    For the Group Item (The Column):

    • wire:sortable.item="id": Identifies the group.
    • wire:sortable.handle: The handle to drag the entire group.
    • wire:sortable-group.item-group="id": Applied to the list inside the group to identify which group the items belong to.

    For the Task Item (The Card):

    • wire:sortable-group.item="id": Identifies the specific item within the group.
    • wire:sortable-group.handle: The handle to drag the item within the group.
    <div wire:sortable="updateGroupOrder" wire:sortable-group="updateTaskOrder" style="display: flex">
        @foreach ($groups as $group)
            <div wire:key="group-{{ $group->id }}" wire:sortable.item="{{ $group->id }}">
                <div style="display: flex">
                    <h4 wire:sortable.handle>{{ $group->label }}</h4>
                    <button wire:click="removeGroup({{ $group->id }})">Remove</button>
                </div>
    
                <ul wire:sortable-group.item-group="{{ $group->id }}">
                    @foreach ($group->tasks()->orderBy('order')->get() as $task)
                        <li wire:key="task-{{ $task->id }}" wire:sortable-group.item="{{ $task->id }}">
                            <span wire:sortable-group.handle>{{ $task->title }}</span>
                            <button wire:click="removeTask({{ $task->id }})">Remove</button>
                        </li>
                    @endforeach
                </ul>
    
                <form wire:submit.prevent="addTask({{ $group->id }}, $event.target.title.value)">
                    <input type="text" name="title">
                    <button>Add Task</button>
                </form>
            </div>
        @endforeach
    
        <form wire:submit.prevent="addGroup">
            <input type="text" wire:model="newGroupLabel">
            <button>Add Task Group</button>
        </form>
    </div>
  4. Implement simple sorting for flat lists

    master

    For simple layouts like a todo list, use the following attributes on your markup:

    • wire:sortable="methodName": Applied to the parent container. methodName is the Livewire method called when the order changes.
    • wire:sortable.item="id": Applied to each draggable item. It must include the unique identifier for the item.
    • wire:sortable.handle: Applied to the specific element within an item that acts as the drag handle.

    Important: Always include a wire:key on sortable items to ensure Livewire tracks DOM changes correctly.

    <ul wire:sortable="updateTaskOrder">
        @foreach ($tasks as $task)
            <li wire:sortable.item="{{ $task->id }}" wire:key="task-{{ $task->id }}">
                <h4 wire:sortable.handle>{{ $task->title }}</h4>
                <button wire:click="removeTask({{ $task->id }})">Remove</button>
            </li>
        @endforeach
    </ul>
  5. Use the wire:sortable directive for simple lists

    master

    The wire:sortable directive enables drag-and-drop reordering for a flat list of items.

    Requirements

    • The container element must have the wire:sortable attribute.
    • Each draggable item must have the wire:sortable.item attribute. The value of this attribute is passed back to your Livewire component.
    • (Optional) If you want to restrict dragging to a specific handle, add an element with the wire:sortable.handle attribute inside your items.
    • (Optional) To prevent specific elements from triggering drag events, add the wire:sortable.ignore attribute.

    Behavior

    When a sort operation completes (sortable:stop), the directive automatically calls the Livewire method specified in your directive call (e.g., wire:sortable="updateOrder"). It passes an array of objects to that method. Each object contains:

    • order: The new 1-based index of the item.
    • value: The string value provided in the wire:sortable.item attribute.

    Example call: wire:sortable="updateOrder"

    <!-- HTML Example -->
    <div wire:sortable="updateOrder">
        <div wire:sortable.item="item-1">Item 1</div>
        <div wire:sortable.item="item-2">Item 2</div>
        <div wire:sortable.item="item-3">
            <span wire:sortable.handle>Drag Me</span> Item 3
        </div>
    </div>
  6. Use the wire:sortable-group directive for nested lists

    master

    The wire:sortable-group directive allows for complex, nested sorting structures (groups containing items).

    Requirements

    • The root container must have the wire:sortable-group attribute.
    • Each sub-group must have the wire:sortable-group.item-group attribute. The value of this attribute is passed to your Livewire method.
    • Each item within a group must have the wire:sortable-group.item attribute. The value of this attribute is passed to your Livewire method.
    • (Optional) Use wire:sortable-group.handle to define a drag handle within items.
    • (Optional) Use the .item-group modifier on the root directive to ensure new groups added via Livewire during runtime are correctly registered: wire:sortable-group.item-group="methodName".

    Behavior

    When sorting is complete, the directive calls your specified Livewire method with an array of group objects. Each group object contains:

    • order: The 1-based index of the group.
    • value: The string value from the wire:sortable-group.item-group attribute.
    • items: An array of objects representing the items within that group, each containing:
      • order: The 1-based index of the item within the group.
      • value: The string value from the wire:sortable-group.item attribute.

    Example call: wire:sortable-group="updateGroups"

    <!-- HTML Example -->
    <div wire:sortable-group.item-group="updateGroups">
        <!-- Group 1 -->
        <div wire:sortable-group.item-group="group-a">
            <div wire:sortable-group.item="val-1">Item A1</div>
            <div wire:sortable-group.item="val-2">Item A2</div>
        </div>
    
        <!-- Group 2 -->
        <div wire:sortable-group.item-group="group-b">
            <div wire:sortable-group.item="val-3">Item B1</div>
        </div>
    </div>