Dispatching Custom Events in Livewire and listening in Alpine

Livewire and Alpine work so well together, almost like a match made in heaven. Perhaps, because they are both authored by the same developer, Caleb Porzio. I'll be showing you in very brief and clear steps how you can work with both in your project, to make them work together

Imagine building an application where users can generate reports from the frontend, and the server takes care of processing and exporting the report as a PDF. The user needs to be notified when the report is ready, so they can navigate to the result page and view or download their report. While you can achieve such a seamless experience with WebSockets or similar setups, we are going to be leveraging Livewire's event and polling features. These two powerful features enable you to send custom events from your backend to your frontend, ensuring a real-time feel and engaging user experience.

Now, let's focus on a scenario where a user generates a report from the frontend, and the server processes the report in the background. Once the report is ready, the server will dispatch a custom event to the frontend, notifying the user and redirecting them to the result page.

Dispatching Custom Events from Livewire Class Components

Livewire allows you to dispatch custom events from a component using the dispatch method. Let's consider a ReportGenerator component that polls the server export directory to check when the report is ready:

// app/Http/Livewire/ReportGenerator.php

namespace App\Http\Livewire;

use Livewire\Component;
use Illuminate\Support\Facades\Storage;

class ReportGenerator extends Component
{
    public $reportStatus = 'pending';

    public function checkReportStatus()
    {
		$reportFilePath = storage_path('app/export/report.pdf');
        if (Storage::exists($reportFilePath)) {
            $this->reportStatus = 'ready';
            $this->dispatch('report-generated', ['url' => route('reports.show', ['file' => 'report.pdf'])]);
        }
    }

    public function render()
    {
		$this->checkReportStatus();
        return view('livewire.report-generator');
    }
}

In this example, the ReportGenerator component polls the server export directory to check when the report is ready. Once the report is ready, the checkReportStatus method dispatches a report-generated event with the URL of the report result page.

Consuming Custom Events in Alpine

To consume the dispatched event in your Alpine code, you can use the x-on directive to bind a function to the event, as shown below:

<!-- resources/views/livewire/report-generator.blade.php -->

<div wire:poll class="flex items-center" x-data="{
    handleReportGenerated(customEvent) {
        window.location.href = customEvent.detail.url;
    }
}" x-on:report-generated.window="handleReportGenerated">
    <!-- Your report generator UI here -->
    <p x-show="reportStatus === 'pending'">Generating report...</p>
    <p x-show="reportStatus === 'ready'">Report is ready!</p>
</div>
Databases in VS Code? Get DevDb

Note that while we are polling using wire:poll, we're using x-on:report-generated.window to listen for the event on the window object, ensuring that the event is captured regardless of where it's dispatched from. Additionally, we're accessing the custom event data via the detail property, as Livewire sends custom events with the data wrapped in the detail property.

I prefer using Livewire's event dispatching system because it provides a simple and elegant way to decouple backend and frontend logic, making it easier to create real-time interactions between your backend and frontend. By leveraging this system, you can create more scalable and maintainable applications that are easier to test and debug.

Conclusion

In this article, we've explored how to dispatch custom events from Livewire class components and consume them in Alpine.js code. By utilizing Livewire's event dispatching system, you can create seamless and intuitive user experiences, making your application more responsive and engaging. Remember to always access the custom event data via the detail property, and you'll be well on your way to unlocking the full potential of custom events in Livewire. Next, you might want to explore other features of Livewire, such as its support for broadcasting events to specific users or channels, to further enhance your application's real-time capabilities.

Wanna chat about what you just read, or anything at all? Click here to tweet at me on 𝕏