Livewire 3.6.10 with Laravel 11: wire:model not binding input value after page refresh

Livewire 3.6.10 with Laravel 11: wire:model not binding input value after page refresh
typescript
Ethan Jackson

I'm working with Laravel 11, Livewire 3.6.10, and Alpine.js (properly configured). I'm encountering an issue where wire:model doesn't bind the value to an input field after a page refresh, even though the variable is correctly set in the component.

What Works

  • Items are listed correctly in a table.
  • Adding a new item works perfectly.
  • Clicking "Edit" immediately after adding an item shows the form with values populated (including the input field).

The Issue

If I refresh the page and then click "Edit" on an item:

  • The variable {{ $name }} displays correctly.
  • But the input field bound with wire:model="name" does not show the value.

Code Snippets

<table class="min-w-full"> <thead> <tr> <th>#NO</th> <th>Name</th> <th>Actions</th> </tr> </thead> <tbody> @foreach ($list as $item) <tr> <td>{{ $loop->iteration }}</td> <td>{{ $item->name }}</td> <td> <button wire:click="edit({{ $item->id }})">Edit</button> </td> </tr> @endforeach </tbody> </table>

Edit Form

{{ $name }} <!-- Displays correctly --> <form wire:submit.prevent="{{ $isEdit ? 'update' : 'store' }}"> <input type="text" wire:model="name"> </form>

Edit method

public function edit($id) { $inventory = ModelsInventory::findOrFail($id); $this->inventory_id = $id; $this->name = $inventory->name; }

Debugging Summary

  • $name is correctly populated.
  • {{ $name }} displays the expected value.
  • However, <input wire:model="name"> does not reflect the value after a page refresh.

Question

Why is the value not binding to the input via wire:model after a page refresh, even though the component variable is correctly populated?

Note: the project is created with starter kit, laravel breeze, it has livewire and alpine configured.

app.js

import Alpine from 'alpinejs' import persist from '@alpinejs/persist' import './bootstrap'; // assuming Livewire's stuff is here // Only register Alpine once (before Livewire boots it) window.Alpine = Alpine Alpine.plugin(persist)

There are no browser console errors.

I have found a code snippet online that says as follow

Force DOM Update with Alpine

<input type="text" wire:model="name" x-data x-init="$nextTick(() => { $el.value = '{{ $name }}' })">

I have tried this snippet, surprisingly it worked.

But the problem is that, I don't want these extra things in my input field, I want to use only wire:model="name" and it should work.

Answer

Since you're using Livewire 3.6.10, Laravel 11, and Alpine.js (which is already configured), the best solution to ensure proper two-way binding after page refresh is:

Use Alpine's @entangle to Bridge Livewire and DOM

Replace this:

<input type="text" wire:model="name">

With this:

<input type="text" x-data x-model="@entangle('name')">

Working Example:

<form wire:submit.prevent="{{ $isEdit ? 'update' : 'store' }}"> <input type="text" x-data x-model="@entangle('name')" class="border rounded p-1"> </form>

Related Articles