Svennnn's avatar

Refresh a lazy island from outside the island

Following use case:

I have a page-component that displays a lot of threads. Loading the threads takes a moment, so I wrapped that access to my

 #[Computed]
    public function threads()

in an

@island(name: 'threads', lazy: true)

That way I can still render the rest of the layout. Including filters, which live outside the island in the same component.

 <x-stupid.button href="#" wire:click="toggleFilter('unread')" :variant="collect($filters)->contains('unread') ? 'primary' : 'default'" size="sm">Ungelesen</x-stupid.button>

Is there a way to trigger the refresh from within toggleFilter?

My list is only updated, from events within the island.

Basicly I want: initaly lazy but after that mutate with the rest of the page

0 likes
5 replies
LaryAI's avatar
Level 58

Certainly! Here’s how you can approach this problem:

Problem Recap

  • You have a lazy @island for displaying threads (@island(name: 'threads', lazy: true)), so it doesn't block other UI parts.
  • Filters/buttons live outside the island.
  • When the filter gets toggled with toggleFilter, you want the island to update and re-fetch threads (i.e., refresh the lazy island component from outside).

Solution

The general approach is to:

  1. Emit an event from outside the island (in your filter handler)
  2. Listen for that event inside the island
  3. Refresh/reload the threads when the event is received

Depending on your stack (Livewire, Blade Islands, Alpine, etc.), this pattern is mostly the same.

Example using Livewire + Blade Islands

1. In your button (outside the island), emit an event

<x-stupid.button 
    href="#" 
    wire:click="toggleFilter('unread')"
    wire:loading.attr="disabled"
    size="sm"
>
    Ungelesen
</x-stupid.button>

In your toggleFilter method (on the main component), emit an event after updating the filters:

public function toggleFilter($filter)
{
    // Your filtering logic here
    // ...
    $this->emit('refreshThreadsIsland');
}

2. Inside your island, listen for the event

Suppose your island renders a Livewire component like this:

@island(name: 'threads', lazy: true)
    <livewire:threads-list :filters="$filters" />
@endisland

In your ThreadsList Livewire component:

Add:

protected $listeners = ['refreshThreadsIsland' => '$refresh'];

This tells Livewire to re-render this component whenever the refreshThreadsIsland event is fired.


Full Example

{{-- Main component --}}
<x-stupid.button 
    href="#"
    wire:click="toggleFilter('unread')"
    size="sm"
>
    Ungelesen
</x-stupid.button>

@island(name: 'threads', lazy: true)
    <livewire:threads-list :filters="$filters" />
@endisland
// In your main Livewire component
public function toggleFilter($filter)
{
    // ... toggle filter logic ...
    $this->emit('refreshThreadsIsland'); // Notify the island to refresh
}
// In App\Http\Livewire\ThreadsList or similar:
class ThreadsList extends Component
{
    protected $listeners = [
        'refreshThreadsIsland' => '$refresh',
    ];
    // ...
}

Key Points

  • Initial load is lazy (renders later), but after that, island listens to global events.
  • Updates can be triggered from the "outside" (main component).
  • Reuse Livewire's event system to bridge communication between components.

Note

If you use a different stack or need to pass parameters with the filter, emit with parameters and handle updating in the island/listener method (not just $refresh).

Let me know if you need a version for Inertia, Alpine Islands, or a different stack!

Svennnn's avatar

The purpose of the island is to NOT have a subcomponent. The lists foreach is within the island

Please or to participate in this conversation.