PHPexp logo PHPexp

Trigger wire:loading on an event from another Livewire component

Published on

When a Laravel Livewire component is loading, you can use wire:loading.block to show a spinner, and wire:loading.remove to hide the rest of the component. Unfortunately, this doesn't work when one component listens to events from another component. Livewire doesn't trigger wire:loading when actions are called by listeners. This might get fixed with Livewire v3, but for now, the workaround described below will work.

Your component that dispatches the event stays the same. Just dispatch the event like you would normally do:

class PeriodSelectElement extends Component
{
    public $from_date;

    public $until_date;

    public function store()
    {
        $this->emit('periodSelected', [
            'from_date' => $this->from_date,
            'until_date' => $this->until_date,
        ]);
    }
}

In the component that receives the event, don't register a listener (since this won't trigger the loading state):

class TableWithData extends Component
{
    protected $listeners = ['periodSelected'];
    
    public function periodSelected($data)
    {
        ['from_date' => $fromDate, 'until_date' => $untilDate] = $data;
    }
}

Instead of registering the listener in the component class, register it in the html instead. To receive the event and trigger the loading state, add this to the html of the component that should receive the event:

<script>
    {{-- Receive the event and trigger the loading state --}}
    document.addEventListener("DOMContentLoaded", () => {
        Livewire.on("periodSelected", (data) => {
            @this.periodSelected(data);
        });
    });
</script>

Registering the listener in the html will trigger the loading state, just like calling a normal action would. Now while your component is loading, you can hide your data, and show your spinner:

<div wire:loading.flex wire:target="periodSelected" wire:key="loading-spinner">
    <x-svg.spinner class="w-8 h-8"/>
</div>

<div wire:loading.remove wire:target="periodSelected" wire:key="data-container">
    {{-- Your data --}}
</div>

Level up your Laravel deployments

If you aren't happy with your current deployment strategy for your Laravel apps, check out my premium deployment script.

Deploy with GitHub Actions Deploy with GitLab CI/CD