Створення компонента висувної панелі за допомогою Livewire

  • Час читання ~5 хв
  • 06.10.2022
Я був шанувальником Laravel Livewire з моменту його першого випуску, і я використовував його багато разів для створення чудових інтерфейсів користувача для програм.

Я був шанувальником Laravel Livewire з моменту його першого випуску, і багато разів використовував його для створення чудових інтерфейсів користувача для програм. Одна з речей, які я вважаю, що я часто роблю, — це створення вилучених компонентів, у які я можу передати інші, щоб у мене не було, наприклад, 20 різних модалів чи слайдів.

У цьому підручнику я розповім про те, як ви можете створити слайд-овер компонент для своїх програм TALL Stack, щоб ви також могли застосувати цей підхід.

Я припускаю, що ви вже встановили Laravel і Livewire і налаштували базову програму. Я буду використовувати Tailwind UI і Tailwind CSS для стилю, тому що я не маю уявлення, як щось розробити.

Почнемо зі створення загального компонента в Livewire під назвою SidePanel, який міститиме весь код і елементи керування, необхідні для відкриття та закриття панелі. Давайте почнемо будувати.

php artisan livewire:make SidePanel --test

Нам спочатку потрібно мати доступний стан, щоб він міг бути відкритим або закритим, що, я впевнений, ви погодитесь, є життєво важливим аспектом бічної панелі.

< br

Тут у нас є стандартний компонент Livewire, налаштований на мій дуже впевнений спосіб. На даний момент у нас є одна властивість під назвою open, яку ми «переплутаємо» на інтерфейсі за допомогою AlpineJS. Нам потрібна пара інших властивостей, щоб ми могли відображати панель і не аварійно завершувати роботу, якщо компонент не передано.

declare(strict_types=1);
 
namespace App\Http\Livewire;
 
use Illuminate\Contracts\View\View as ViewContract;
use Illuminate\Support\Facades\View;
use Livewire\Component;
 
final class SidePanel extends Component
{
    public bool $open = false;
 
    public function render(): ViewContract
    {
        return View::make(
            view: 'livewire.side-panel',
        );
    }
}

У нас є назва за замовчуванням і властивість component, яка дозволяє нам вибрати, який компонент завантажувати. Таким чином, інші компоненти, які спілкуються з ним, можуть вказувати йому, що завантажувати, і передавати заголовок для відображення. Давайте подивимося на шаблон для цього компонента:

declare(strict_types=1);
 
namespace App\Http\Livewire;
 
use Illuminate\Contracts\View\View as ViewContract;
use Illuminate\Support\Facades\View;
use Livewire\Component;
 
final class SidePanel extends Component
{
    public bool $open = false;
    public string $title = 'Default Panel';
    public string $component = '';
 
    public function render(): ViewContract
    {
        return View::make(
            view: 'livewire.side-panel',
        );
    }
}

Тут у нас є досить багато розмітки, щоб контролювати його вигляд і поведінку, використовуючи @entangle для зв’язку між AlpineJS і Livewire. Ми перевіряємо, чи встановлено component, і, якщо ні, відображаємо порожній стан. Далі нам потрібно запустити це з інших компонентів, надіславши йому деякі дані, щоб ми могли вибрати компонент для завантаження та назву для встановлення. Це працюватиме з Livewire або Alpine, але в моєму прикладі я використаю інший компонент Livewire, щоб відкрити панель.

<section
    x-data="{ open: @entangle('open') }"
    @keydown.window.escape="open = false"
    x-show="open"
    x-cloak
    class="relative z-10"
    aria-labelledby="slide-over-title"
    x-ref="dialog"
    aria-modal="true"
>
 
    <div
        x-show="open"
        x-cloak
        x-transition:enter="ease-in-out duration-500"
        x-transition:enter-start="opacity-0"
        x-transition:enter-end="opacity-100"
        x-transition:leave="ease-in-out duration-500"
        x-transition:leave-start="opacity-100"
        x-transition:leave-end="opacity-0"
        class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity"
    ></div>
 
    <div class="fixed inset-0 overflow-hidden">
        <div class="absolute inset-0 overflow-hidden">
            <div class="pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10">
 
                <div
                    x-show="open"
                    x-cloak
                    x-transition:enter="transform transition ease-in-out duration-500 sm:duration-700"
                    x-transition:enter-start="translate-x-full"
                    x-transition:enter-end="translate-x-0"
                    x-transition:leave="transform transition ease-in-out duration-500 sm:duration-700"
                    x-transition:leave-start="translate-x-0"
                    x-transition:leave-end="translate-x-full"
                    class="pointer-events-auto w-screen max-w-md"
                    @click.away="open = false"
                >
                    <div class="flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl">
                        <header class="px-4 sm:px-6">
                            <div class="flex items-start justify-between">
                                <h2 class="text-lg font-medium text-gray-900" id="slide-over-title">
                                    Panel title
                                </h2>
                                <div class="ml-3 flex h-7 items-center">
                                    <button
                                        type="button"
                                        class="rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
                                        @click="open = false"
                                    >
                                        <span class="sr-only">Close panel</span>
                                        <svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
                                            <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path>
                                        </svg>
                                    </button>
                                </div>
                            </div>
                        </header>
                        <article class="relative mt-6 flex-1 px-4 sm:px-6">
                            @if ($component)
                                @livewire($component)
                            @else
                                <div class="absolute inset-0 px-4 sm:px-6">
                                    <div class="h-full border-2 border-dashed border-gray-200" aria-hidden="true"></div>
                                </div>
                            @endif
                        </article>
                    </div>
                </div>
 
            </div>
        </div>
    </div>
</section>

Ми передаємо три параметри за допомогою методу emit. По-перше, назва події, яку ми запускаємо. По-друге, назва панелі. Нарешті, ми хочемо передати сам компонент так, ніби ми завантажуємо його за допомогою директиви livewire у вашому поданні.

$this->emit('openPanel', 'New Title', 'component.name.with-namespace');

Тепер нам потрібно попросити наш компонент бічної панелі прослухати цю подію та мати метод, який керуватиме логікою оновлення його властивостей.

Коли слухач приймає всі необхідні параметри та Alpine обробляє відкритий і закритий стан, ми можемо закрити цю панель і замінити показаний компонент.

declare(strict_types=1);
 
namespace App\Http\Livewire;
 
use Illuminate\Contracts\View\View as ViewContract;
use Illuminate\Support\Facades\View;
use Livewire\Component;
 
final class SidePanel extends Component
{
    public bool $open = false;
    public string $title = 'Default Panel';
    public string $component = '';
 
    protected $listeners = [
        'openPanel'
    ];
 
    public function openPanel(string $title, string $component): void
    {
        $this->open = true;
        $this->title = $title;
        $this->component = $component;
    }
 
    public function render(): ViewContract
    {
        return View::make(
            view: 'livewire.side-panel',
        );
    }
}

Цей підхід дозволив мені створити чистий користувач інтерфейси, які відкривають окремий компонент за потреби. Крім того, компонент, через який ми передаємо на панель, усе ще можна використовувати як ізольований компонент для перегляду.

Як ви обробляєте ці варіанти використання у своїх проектах? Як, на вашу думку, це зміниться в Livewire v3? Поділіться з нами своїми думками в Twitter.

Оригінал
Yurij Finiv

Yurij Finiv

Full stack

ABOUT

I'm full stack laravel developer

I knew my call in programming back in 2006.

WORK EXPERIENCE
CONTACT
Ukraine, Lutsk
+380979856297