Hey everyone! š
I've been running into a weird issue with Livewire v3 validation errors when working with nested components and dynamic array inputs.
The validation errors exist, but they aren't being displayed properly in my Blade templates. š©
Hereās what I tested so far, and Iām wondering: Whatās the correct way to handle this in Livewire v3?
<?php
namespace App\Livewire;
use Livewire\Component;
use Illuminate\Validation\ValidationException;
class TodoList extends Component
{
public array $todos = [];
public function addTodo(): void
{
$this->todos[] = [
'title' => '',
'completed' => false,
];
}
public function removeTodo(int $index): void
{
unset($this->todos[$index]);
$this->todos = array_values($this->todos); // Re-index array
}
public function save(): void
{
$this->validate([
'todos' => ['required', 'array', 'min:1'],
'todos.*.title' => ['required', 'string', 'min:3'],
]);
}
public function render()
{
return view('livewire.todo-list');
}
}
todo-list.blade.php
<div>
<button wire:click="addTodo" class="bg-blue-500 text-white px-4 py-2 rounded">Add Todo</button>
<ul class="mt-4 space-y-2">
@foreach ($todos as $index => $todo)
<livewire:todo-item
:todo="$todo"
:index="$index"
wire:key="todo-{{ $index }}"
/>
@endforeach
</ul>
<button wire:click="save" class="bg-green-500 text-white px-4 py-2 rounded mt-4">Save</button>
</div>
TodoItem
<?php
namespace App\Livewire;
use Livewire\Component;
class TodoItem extends Component
{
public array $todo;
public int $index;
public function render()
{
return view('livewire.todo-item');
}
}
todo-item.blade.php
<li class="flex items-center space-x-4 border p-2 rounded">
<!-- Checkbox -->
<input type="checkbox" wire:model="todo.completed" class="h-5 w-5">
<!-- Title Input -->
<input type="text" wire:model="todo.title" class="border rounded p-2 flex-1">
<!-- Remove Button -->
<button type="button" wire:click="$emitUp('removeTodo', {{ $index }})" class="px-2 py-1 bg-red-500 text-white rounded">
Remove
</button>
@if ($errors->has("todos.$index.title"))
<div class="mt-1 text-sm text-red">
{{ $errors->first("todos.$index.title") }}
</div>
@endif
also tried:
@error("todos.0.title")
<div class="mt-1 text-sm text-red">{{ $message }}</div>
@enderror
also
@foreach ($errors->get("todos.$loop->index.title") as $message)
<span class="text-red text-sm">{{ $message }}</span>
@endforeach
also
@error("todos.{$index}.title")
<span class="text-red text-sm">{{ $message }}</span>
@enderror
</li>
I ran a dd($e->errors()) inside save() and got:
array:1 [ā¼
"todos.0.title" => array:1 [ā¼
0 => "O tĆtulo da tarefa Ć© obrigatório."
]
]
So the validation is working ā
, but Livewire isnāt displaying the error messages properly in the Blade template ā.