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

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>

Enjoyed this article?

Check out more content on our blog or follow us on social media.

Browse more articles