Tworzenie komponentów wielokrotnego użytku to podstawa skalowalnych aplikacji. W kontekście Livewire (w połączeniu z ekosystemem Laravel) mamy kilka sposobów na przekazywanie parametrów do komponentów, wykorzystywanie slotów oraz budowanie bardziej złożonych struktur takich jak modale.
W niniejszym artykule omówimy:
- Jak przekazywać parametry do komponentu Livewire już w momencie jego wywołania.
- Czym jest i jak działa metoda
mount($param). - Jak wykorzystać mechanizmy slotów Blade – również wewnątrz komponentów Livewire.
- Jak stworzyć re-używalny komponent, np.
Modal, który może wyświetlać treść z innego komponentu i reagować na zdarzenia (otwarcie, zamknięcie, potwierdzenie akcji).
Artykuł nawiązuje do poprzednich wpisów:
Przekazywanie parametrów do komponentu Livewire
1. Metoda mount($param)
W Livewire możemy definiować metodę mount(), która zostanie wywołana podczas inicjalizacji komponentu. Pozwala ona wstępnie zainicjalizować dane w komponencie:
use Livewire\Component;
class ExampleComponent extends Component
{
public $someData;
public function mount($dataFromParent)
{
$this->someData = $dataFromParent;
}
public function render()
{
return view('livewire.example-component');
}
}
Dzięki temu, gdy odpalimy komponent za pomocą:
Parametr $dataFromParent automatycznie trafi do metody mount(). Jest to wyjątkowo przydatne w sytuacji, gdy chcemy wstępnie ustawić stan komponentu na podstawie danych z rodzica lub kontekstu (np. aktualnie zalogowanego użytkownika).
2. Przekazywanie danych przez atrybuty komponentu
W widoku Blade możemy przekazywać dane do komponentu w następujący sposób:
W klasie Livewire możemy wtedy zdefiniować publiczne właściwości o tych samych nazwach:
public $someProp;
public $anotherProp;
public function mount()
{
// Te właściwości już zawierają przekazane wartości
}
Można też użyć metody mount($someProp, $anotherProp) i zmapować przekazane właściwości do parametrów funkcji. Oba podejścia są poprawne – wybór zależy od preferencji i potrzeb.
Tworzenie komponentów z slotami
1. Sloty w Blade
Laravel Blade posiada mechanizm slotów, dzięki któremu możemy w strukturze naszego komponentu wyznaczyć obszary, do których „dostarcza się” zawartość z zewnątrz.
Najprostszy przykład (tradycyjny Blade, bez Livewire):
Header
{{ $slot }}
Aby użyć takiego layoutu:
Treść slotu głównego
2. Sloty a Livewire
Livewire nie wprowadza własnych, osobnych slotów, lecz bazuje na standardowym mechanizmie Blade.
Gdy tworzymy komponent Livewire, jego kod Blade może zawierać sloty (tak samo, jak każdy plik Blade), ale nie będzie to mechanizm dedykowany wyłącznie Livewire. Na przykład:
{{ $title }}
{{ $slot }}
Tu widzimy nazwany slot $title oraz domyślny $slot. Następnie w miejscu, gdzie umieszczamy nasz komponent, możemy wypełnić te sloty:
Usuwanie zadania
Czy na pewno chcesz usunąć to zadanie?
Takie podejście pozwala dość elastycznie sterować zawartością modala bez przepisywania kodu HTML.
Re-używalne komponenty: przykład Modal
1. Scenariusz
Załóżmy, że chcemy stworzyć uniwersalny komponent Modal, który możemy wykorzystywać w różnych miejscach aplikacji. Czasem ma on służyć do potwierdzania usunięcia rekordu, a czasem do wyświetlenia innej treści.
2. Tworzenie komponentu
Zaczynamy od wygenerowania komponentu:
php artisan make:livewire Modal
Pojawią się dwa pliki:
app/Http/Livewire/Modal.php– klasa komponentu.resources/views/livewire/modal.blade.php– widok Blade.
Klasa: Modal.php
namespace App\Http\Livewire;
use Livewire\Component;
class Modal extends Component
{
// Parametry modyfikujące zachowanie modala
public $show = false; // Decyduje, czy modal jest aktualnie wyświetlony
public $title = 'Uwaga'; // Tytuł modala, domyślnie "Uwaga"
public $message = ''; // Treść w modalu
public function mount($title = null, $message = null)
{
if ($title) {
$this->title = $title;
}
if ($message) {
$this->message = $message;
}
}
public function showModal()
{
$this->show = true;
}
public function hideModal()
{
$this->show = false;
}
// Zdarzenie potwierdzenia akcji
public function confirm()
{
// Możemy np. wyemitować zdarzenie do rodzica z informacją,
// że akcja została potwierdzona
$this->emit('modalConfirmed');
$this->hideModal();
}
public function render()
{
return view('livewire.modal');
}
}
Kilka uwag do powyższego:
$showkontroluje, czy modal jest widoczny czy nie. Dzięki temu możemy manipulować tym stanem w Livewire, bez JavaScriptu.- W
mount($title, $message)umożliwiamy przekazywanie parametrów do wstępnego ustawienia tytułu i treści. - W
confirm()emitujemy zdarzeniemodalConfirmed, by na zewnątrz ktoś mógł się dowiedzieć o akcji potwierdzenia.
Widok: modal.blade.php
@if($show)
{{ $title }}
@if($message)
{{ $message }}
@endif
{{ $slot }}
@endif
- Gdy
$showjesttrue, wyświetlamy warstwę zasłaniającą i okno modala. - Zawartość modala może być częściowo wypełniona przez parametry (
$title,$message), a częściowo przez slot ({{ $slot }}).
3. Zagnieżdżanie komponentu Modal
Teraz możemy użyć Modal w innym komponencie, np. TaskList, by potwierdzać usunięcie zadania.
Przykład: TaskList z integracją modala
namespace App\Http\Livewire;
use App\Models\Task;
use Livewire\Component;
class TaskList extends Component
{
public $selectedTaskId;
protected $listeners = ['modalConfirmed' => 'deleteTask'];
public function confirmDelete($taskId)
{
$this->selectedTaskId = $taskId;
// Emitujemy do komponentu Modal, by się pokazał
$this->emitTo('modal', 'showModal');
}
public function deleteTask()
{
if ($this->selectedTaskId) {
Task::find($this->selectedTaskId)?->delete();
$this->selectedTaskId = null;
}
}
public function render()
{
return view('livewire.task-list', [
'tasks' => Task::all()
]);
}
}
W powyższym kodzie:
confirmDelete($taskId)– użytkownik klika na przycisk usunięcia,selectedTaskIdsię ustawia, a następnie wywołujemyemitTo('modal', 'showModal'), by pokazać okno modalne (o ile mamy przypisany aliasmodalw widoku).- Gdy w modalu nastąpi
confirm(), modal wyemitujemodalConfirmed. TaskList odbierze to zdarzenie i uruchomideleteTask(). deleteTask()usunie rekord z bazy.
Widok: task-list.blade.php
Lista zadań
@foreach($tasks as $task)
-
{{ $task->name }}
@endforeach
Dzięki wire:key="modal" mamy pewność, że odwołujemy się do konkretnego wystąpienia komponentu Modal. Gdy wywołamy emitTo('modal', 'showModal'), Livewire zlokalizuje ten właśnie komponent i uruchomi metodę showModal().
Uwaga: Aby skorzystać z
emitTo('modal', 'showModal'), komponentModalmusi mieć nazwę aliasumodalzarejestrowaną np. w plikuapp/Providers/AppServiceProvider.phplub innym miejscu, gdzie definiujemy aliasy Livewire.
Możemy zrobić to np. wroutes/web.php:
use App\Http\Livewire\Modal;
Livewire::component('modal', Modal::class);
Dzięki temu
<livewire:modal ...>jest interpretowane jakoModal::class.
Ćwiczenia
Stworzyć komponent
Modal– tak jak w przykładzie powyżej:- Dodaj metody
showModal()ihideModal(). - Udostępnij parametry
titleimessage. - Dodaj slot w widoku, aby można było wypełnić modal własną treścią.
- Dodaj metody
Zagnieździć komponent
Modalw innym komponencie – np. wTaskList:- Wywołaj
emitTo('modal', 'showModal')przy kliknięciu przycisku „Usuń zadanie”. - Przekazuj do modala parametry (np. inny tytuł, treść).
- Wywołaj
Obsługa eventów – Po kliknięciu „Potwierdź” w modalu:
- Wyemituj zdarzenie
modalConfirmed, aby komponent nadrzędny wykonał właściwą akcję (np. usunięcie zadania).
- Wyemituj zdarzenie
(Opcjonalnie) Rozbudować modal o dodatkowe parametry lub sloty:
- Możesz chcieć przekazać np. przycisk potwierdzenia w innym stylu, inny komunikat itd.
- Możesz dodać
wire:loadingw modalu, aby zasygnalizować użytkownikowi, że trwa przetwarzanie.
Ćwiczenie 1: Stworzyć komponent Modal
Celem jest stworzenie prostego komponentu Livewire o nazwie Modal, który:
- Posiada metody do pokazywania i chowania modala (
showModal(),hideModal()). - Udostępnia publiczne właściwości, np.
title,message. - Pozwala wypełnić wnętrze modalnego okna przez slot (np. dodatkowym tekstem, formularzem).
Krok 1. Wygeneruj komponent
php artisan make:livewire Modal
W efekcie otrzymasz plik klasy komponentu app/Http/Livewire/Modal.php oraz widok resources/views/livewire/modal.blade.php.
Krok 2. Uzupełnij klasę Modal.php
Poniżej przykładowa implementacja:
title = $title;
}
if ($message) {
$this->message = $message;
}
}
/**
* Pokazuje modal
*/
public function showModal()
{
$this->show = true;
}
/**
* Chowa modal
*/
public function hideModal()
{
$this->show = false;
}
/**
* Akcja wykonywana przy potwierdzeniu
*/
public function confirm()
{
// Przykład: emitujemy zdarzenie do innego komponentu
$this->emit('modalConfirmed');
$this->hideModal();
}
public function render()
{
return view('livewire.modal');
}
}
Krok 3. Uzupełnij widok modal.blade.php
Przykładowa zawartość:
@if($show)
{{ $title }}
@if($message)
{{ $message }}
@endif
{{ $slot }}
@endif
Gotowe! Masz już komponent Modal, który można gdzieś wstawić i kontrolować jego widoczność za pomocą metod showModal() i hideModal(). Slot pozwala wypełnić modal własną treścią w momencie użycia.
Ćwiczenie 2: Zagnieżdzić komponent Modal w innym komponencie
Załóżmy, że mamy komponent TaskList, który wyświetla listę zadań. Chcemy, by po kliknięciu w przycisk „Usuń” wyświetlało się okno Modal z pytaniem o potwierdzenie.
Krok 1. Dopisz alias modal (opcjonalne)
Aby łatwiej korzystać z Modal, możemy w pliku routes/web.php (lub AppServiceProvider) zadeklarować:
use App\Http\Livewire\Modal;
use Livewire\Livewire;
Livewire::component('modal', Modal::class);
Dzięki temu <livewire:modal /> będzie rozpoznawane jako Modal::class.
Krok 2. W komponencie TaskList zaimplementuj wywołanie modala
Plik klasy TaskList.php
'deleteTask'];
/**
* Po kliknięciu „Usuń”, ustawiamy ID zadania i emitujemy do Modal, żeby się pokazał.
*/
public function confirmDelete($taskId)
{
$this->selectedTaskId = $taskId;
// Kierujemy zdarzenie bezpośrednio do komponentu "modal"
$this->emitTo('modal', 'showModal');
}
/**
* Wywołane po potwierdzeniu w modalu (modalConfirmed).
*/
public function deleteTask()
{
if ($this->selectedTaskId) {
Task::find($this->selectedTaskId)?->delete();
$this->selectedTaskId = null;
}
}
public function render()
{
return view('livewire.task-list', [
'tasks' => Task::all()
]);
}
}
Wyjaśnienia:
confirmDelete($taskId)– metoda uruchamiana np. po kliknięciu przycisku „Usuń”. Ustawia zmiennąselectedTaskId, a następnieemitTo('modal', 'showModal'), co zasygnalizuje naszemu komponentowiModal, żeby się pokazał.deleteTask()– zostanie wywołane wtedy, gdy wModalklikniemy przycisk „Potwierdź” (bo wModal::confirm()mamy$this->emit('modalConfirmed')).
Plik widoku task-list.blade.php
Lista zadań
@foreach($tasks as $task)
-
{{ $task->name }}
@endforeach
Gotowe! Teraz po kliknięciu przycisku „Usuń” w TaskList, modal zostanie wywołany, a gdy w nim klikniesz „Potwierdź” – nastąpi usunięcie zadania z bazy.
Ćwiczenie 3: Obsługa eventów
Z poprzednich kroków już właściwie mamy implementację obsługi eventów w Modal. Kluczowe elementy to:
- W
Modal:
public function confirm()
{
$this->emit('modalConfirmed');
$this->hideModal();
}
- W
TaskList:
protected $listeners = ['modalConfirmed' => 'deleteTask'];
Dzięki temu, gdy Modal wyemituje modalConfirmed, w TaskList zostanie wywołana metoda deleteTask().
Tym samym potwierdzamy, że całe przepływy zdarzeń już działają – klikasz w Modal, a akcja jest wykonywana w TaskList.
Gotowe! Teraz po kliknięciu przycisku „Usuń” w TaskList, modal zostanie wywołany, a gdy w nim klikniesz „Potwierdź” – nastąpi usunięcie zadania z bazy.
Ćwiczenie 4 (Opcjonalne): Rozszerzyć modal o dodatkowe parametry / sloty
Możesz wzbogacić swój modal o jeszcze większą elastyczność:
Dodaj slot z innym przyciskiem potwierdzenia
Jeśli chcesz, by w różnych kontekstach nazwa przycisku potwierdzenia była inna, możesz przygotować dodatkowy slot. Przykład:
{{ $buttons ?? '' }}
W momencie osadzania modala:
Wyspecjalizowane eventy
Zamiast jednego eventumodalConfirmed, możesz mieć np.modalActionAcceptedimodalActionRejected. Wtedy w zależności od kontekstu – potwierdzenie wywołuje inną akcję w komponencie nadrzędnym, a rezygnacja inną.wire:loading
Jeśli wconfirm()uruchamiasz czasochłonny proces, można dodaćwire:loadingdo przycisku, by zasygnalizować użytkownikowi, że coś się dzieje:
Przetwarzanie...
Podsumowanie
Powyższe ćwiczenia pokazują, jak tworzyć komponenty wielokrotnego użytku (w tym przypadku Modal), jak przekazywać do nich parametry (title, message) oraz jak łączyć je z innymi komponentami za pomocą eventów i komunikacji (emit, emitTo). W dużej mierze bazują one na wcześniejszych artykułach, ale w bardziej praktycznej formie.
Najważniejsze kroki, które warto zapamiętać:
- Generowanie komponentu –
php artisan make:livewire NazwaKomponentu. - Publiczne właściwości i metoda
mount()– służą do inicjalizacji i odbierania parametrów wejściowych. - Metoda
render()– definiuje, jak ma wyglądać widok i co do niego przekazujemy. emit()iemitTo()– umożliwiają komunikację między komponentami (np. z modala do listy zadań).- Sloty w Blade – pozwalają zagnieździć w komponencie część widoku, która może różnić się w zależności od kontekstu.
Dzięki temu możesz tworzyć naprawdę elastyczne, zagnieżdżone i w pełni re-używalne komponenty w ekosystemie Laravel + Livewire. Jeśli w Twojej aplikacji pojawią się inne, bardziej skomplikowane przypadki (np. komponent tabów, panel boczny itp.), możesz śmiało wykorzystać te same wzorce. Powodzenia w dalszym rozwijaniu aplikacji!