Dynamic Page Reordering with Laravel Livewire and Up/Down Arrows

Dynamic Page Reordering with Laravel Livewire and Up/Down Arrows.

Enhance the visual appeal and organization of your website by incorporating a neatly arranged list/page/menu in the footer area. You have the option to display it in alphabetical order or based on unique identifiers. Strategically placing vital links at the top can captivate user attention, while the rest gracefully follow below. This practice is particularly beneficial when working on expansive projects, as it ensures that key links are showcased prominently and arranged in a meaningful order, contributing to a more engaging and user-friendly experience.

Reordering the list using Laravel Livewire

Here we are not using any Laravel packages for changing the position of the list. Just the arrows to move one step up or down to rearrange the position.

If you like to use the packages get any of them:

For this example, we are using the page model. So you have to add the position column in the page table. $table->unsignedInteger() because we do not want the negative numbers to be stored.

/**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('pages', function (Blueprint $table) {
            $table->id();
            $table->unsignedInteger('position')->nullable();
            $table->string('title');
            $table->text('description');

            $table->timestamps();
        });
    }

Make Livewire component: php artisan make:livewire page-list

Implement the logic:

// app/Http/Livewire/PageList.php

class PageList extends Component
{
    public $pages = [];

    public function mount()
    {
        $this->pages = Page::orderBy('position')->get();
    }

    public function moveUp($pageId)
    {
        $page = Page::find($pageId);
        $previousPage = Page::where('position', '<', $page->position)->orderBy('position', 'desc')->first();

        if ($previousPage) {
            $tempPosition = $page->position;
            $page->position = $previousPage->position;
            $previousPage->position = $tempPosition;
            $page->save();
            $previousPage->save();
            $this->pages = Page::orderBy('position')->get();
        }
    }

    public function moveDown($pageId)
    {
        $page = Page::find($pageId);
        $previousPage = Page::where('position', '>', $page->position)->orderBy('position', 'asc')->first();

        if ($previousPage) {
            $tempPosition = $page->position;
            $page->position = $previousPage->position;
            $previousPage->position = $tempPosition;
            $page->save();
            $previousPage->save();
            $this->pages = Page::orderBy('position')->get();
        }
    }

    public function render()
    {
        return view('livewire.page-list');
    }
}

Create the blade view:

<table>
    <thead>
        <tr>
            <th>Title</th>
            <th>Position</th>
            <th>Actions</th>
        </tr>
    </thead>
    <tbody>
        @foreach ($pages as $page)
            <tr>
                <td>{{ $page->title }}</td>
                <td>{{ $page->position }}</td>
                <td>
                    @if ($page->position > 1)
                      <button wire:click="moveUp({{ $page->id }})">↑</button>
                    @endif
                    @if ($page->position < $pages->max('position'))
                      <button wire:click="moveDown({{ $page->id }})">↓</button>
                    @endif
                </td>
            </tr>
        @endforeach
    </tbody>
</table>

Include the component in your view:

// In your main view or layout

<div>
    @livewire('page-list')
</div>

Related Posts