Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

RileyGWeb's avatar

Livewire wire:model update breaks entire page

I have a function that simply gets upcoming shows from the database, and a loop that displays them.

I've stripped these down to their most basic parts for this.

// Controller
public $filterPrivate = false; 

public function loadShows()
{
    $currentTimestamp = now()->timestamp;
    $query = Event::with('socialLinks', 'details')
        ->where('Date', '>=', $currentTimestamp)
        ->where('Status', 'Booked');

	// Private show filtering happens in here

    $shows = $query->get();
	$this->shows = $shows;
}
{{-- View --}}
<div><input type="checkbox" wire:model="filterPrivate"> Show private events</div>

@foreach($shows as $show)
	(show info)
@endforeach

My problem is that when I click the filtering checkbox, all of my shows go blank on the front-end. The cards that display them are still there, but the data is missing. Just blank boxes, except for the unix-based show dates which revert to Jan 1st, 1970 on all of them.

Something is causing the data to be lost in there and I can't figure out what.

I've tried many things, most interesting of which being adding this loop:

$this->shows = $shows->take($this->showsPerPage);
$this->showNames = [];
foreach ($this->shows as $show) {
    $this->showNames[] = $show->display_name;
}

...right below where shows are assigned to $this->shows. It works perfectly and I see all the show names. This tells me that the data is still there, this is just a Livewire bug.

How can I fix this?

0 likes
4 replies
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

It sounds like the issue you're experiencing may be related to Livewire's reactivity and lifecycle hooks. When you update a property that is bound to wire:model, Livewire will re-render the component and call the render method again. If your loadShows method is not called again after the update, the $shows property may not be properly populated.

Here's a potential solution to ensure that your loadShows method is called whenever the filterPrivate property changes:

// Controller
use Livewire\Component;

class ShowEventsComponent extends Component
{
    public $filterPrivate = false;
    public $shows = [];

    public function mount()
    {
        $this->loadShows();
    }

    public function updatedFilterPrivate()
    {
        $this->loadShows();
    }

    public function loadShows()
    {
        $currentTimestamp = now()->timestamp;
        $query = Event::with('socialLinks', 'details')
            ->where('Date', '>=', $currentTimestamp)
            ->where('Status', 'Booked');

        if ($this->filterPrivate) {
            // Apply additional filtering for private shows if needed
        }

        $this->shows = $query->get();
    }

    public function render()
    {
        return view('livewire.show-events');
    }
}
{{-- View --}}
<div>
    <input type="checkbox" wire:model="filterPrivate"> Show private events
</div>

@foreach($shows as $show)
    {{-- show info --}}
@endforeach

In this solution, I've added an updatedFilterPrivate method to the Livewire component. This method is a lifecycle hook that gets called automatically by Livewire whenever the filterPrivate property changes. Inside this method, we call loadShows to refresh the list of shows based on the new filter value.

Additionally, I've added a mount method, which is another lifecycle hook that is called when the component is initially mounted. This ensures that loadShows is called when the component is first loaded, populating the $shows property.

Make sure that your Livewire component is properly set up to use these lifecycle hooks and that the render method returns the correct view. With these changes, your filtering checkbox should work as expected, and the shows should be displayed correctly when the checkbox is toggled.

1 like
Snapey's avatar

you should get the shows in the render method and pass to the view as you would a regular controller

If you don't, you are sending way more data than you need between the client and the server and potentially exposing model properties that should remain private

Also, you forgot the golden rule of livewire - if you have a foreach loop in blade, always use wire:key

1 like
RileyGWeb's avatar

@Snapey So more like this?

class ShowEventsComponent extends Component
{
    public $filterPrivate = false;

    public function updatedFilterPrivate()
    {
        $this->loadShows(); // How do I handle this then? It is what solved my issue
    }

    public function render()
    {
        $currentTimestamp = now()->timestamp;
        $query = Event::with('socialLinks', 'details')
            ->where('Date', '>=', $currentTimestamp)
            ->where('Status', 'Booked');

        if ($this->filterPrivate) {
            // additional filtering
        }

		$shows = $query->get();

        return view('livewire.show-events', ['shows' => $shows]);
    }
}

Please or to participate in this conversation.