docs/attribute-validate.md
The #[Validate] attribute associates validation rules with component properties, enabling automatic real-time validation and clean rule declaration.
Apply the #[Validate] attribute to properties that need validation:
<?php // resources/views/components/post/⚡create.blade.php
use Livewire\Attributes\Validate;
use Livewire\Component;
use App\Models\Post;
new class extends Component {
#[Validate('required|min:3')] // [tl! highlight]
public $title = '';
#[Validate('required|min:3')] // [tl! highlight]
public $content = '';
public function save()
{
$this->validate();
Post::create([
'title' => $this->title,
'content' => $this->content,
]);
return redirect('/posts');
}
};
?>
<div>
<input type="text" wire:model="title">
@error('title') <span class="error">{{ $message }}</span> @enderror
<textarea wire:model="content"></textarea>
@error('content') <span class="error">{{ $message }}</span> @enderror
<button wire:click="save">Save Post</button>
</div>
With #[Validate], Livewire automatically validates properties on each update, providing instant feedback to users.
When you add #[Validate] to a property:
$this->validate() before saving to ensure all properties are validatedBy default, #[Validate] validates properties as they're updated:
<?php // resources/views/components/⚡registration.blade.php
use Livewire\Attributes\Validate;
use Livewire\Component;
new class extends Component {
#[Validate('required|email|unique:users,email')]
public $email = '';
#[Validate('required|min:8')]
public $password = '';
};
?>
<div>
<input type="email" wire:model.live.blur="email">
@error('email') <span>{{ $message }}</span> @enderror
<input type="password" wire:model.live.blur="password">
@error('password') <span>{{ $message }}</span> @enderror
</div>
As users fill out the form, they receive immediate validation feedback.
To validate only when explicitly calling $this->validate(), use onUpdate: false:
<?php // resources/views/components/post/⚡create.blade.php
use Livewire\Attributes\Validate;
use Livewire\Component;
use App\Models\Post;
new class extends Component {
#[Validate('required|min:3', onUpdate: false)] // [tl! highlight]
public $title = '';
#[Validate('required|min:3', onUpdate: false)] // [tl! highlight]
public $content = '';
public function save()
{
$validated = $this->validate();
Post::create($validated);
return redirect('/posts');
}
};
Now validation only runs when save() is called, not on every property update.
Customize the field name in validation messages:
#[Validate('required', as: 'date of birth')] // [tl! highlight]
public $dob;
Error message will be "The date of birth field is required" instead of "The dob field is required".
Override default validation messages:
#[Validate('required', message: 'Please provide a post title')] // [tl! highlight]
public $title;
For multiple rules, use multiple attributes:
#[Validate('required', message: 'Please provide a post title')]
#[Validate('min:3', message: 'This title is too short')]
public $title;
Validate array properties and their children:
<?php // resources/views/components/⚡task-list.blade.php
use Livewire\Attributes\Validate;
use Livewire\Component;
new class extends Component {
#[Validate([
'tasks' => 'required|array|min:1',
'tasks.*' => 'required|string|min:3',
])]
public $tasks = [];
public function addTask()
{
$this->tasks[] = '';
}
};
This validates both the array itself and each individual task.
[!warning] Rule objects not supported PHP attributes can't use Laravel's Rule objects directly. For complex rules like
Rule::exists(), use arules()method instead:phpprotected function rules() { return [ 'email' => ['required', 'email', Rule::unique('users')->ignore($this->userId)], ]; }
Use #[Validate] when:
Use rules() method when:
Here's a complete contact form with validation:
<?php // resources/views/pages/⚡contact.blade.php
use Livewire\Attributes\Validate;
use Livewire\Component;
use App\Mail\ContactMessage;
use Illuminate\Support\Facades\Mail;
new class extends Component {
#[Validate('required|min:2', as: 'name')]
public $name = '';
#[Validate('required|email')]
public $email = '';
#[Validate('required')]
public $subject = '';
#[Validate('required|min:10', as: 'message')]
public $message = '';
public function submit()
{
$validated = $this->validate();
Mail::to('[email protected]')->send(new ContactMessage($validated));
session()->flash('success', 'Message sent successfully!');
$this->reset();
}
};
?>
<div>
@if (session('success'))
<div class="alert">{{ session('success') }}</div>
@endif
<form wire:submit="submit">
<div>
<input type="text" wire:model.live.blur="name" placeholder="Your name">
@error('name') <span class="error">{{ $message }}</span> @enderror
</div>
<div>
<input type="email" wire:model.live.blur="email" placeholder="Your email">
@error('email') <span class="error">{{ $message }}</span> @enderror
</div>
<div>
<input type="text" wire:model.live.blur="subject" placeholder="Subject">
@error('subject') <span class="error">{{ $message }}</span> @enderror
</div>
<div>
<textarea wire:model.live.blur="message" placeholder="Your message"></textarea>
@error('message') <span class="error">{{ $message }}</span> @enderror
</div>
<button type="submit">Send Message</button>
</form>
</div>
Users get immediate feedback as they fill out the form, with friendly field names and helpful error messages.
For comprehensive documentation on validation, including form objects, custom rules, and testing, see the Validation documentation.
#[Validate(
mixed $rule = null,
?string $attribute = null,
?string $as = null,
mixed $message = null,
bool $onUpdate = true,
bool $translate = true,
)]
| Parameter | Type | Default | Description |
|---|---|---|---|
$rule | mixed | null | The validation rule(s) to apply |
$attribute | ?string | null | Custom attribute name for validation error messages |
$as | ?string | null | Friendly name to display in validation error messages |
$message | mixed | null | Custom error message(s) for validation failures |
$onUpdate | bool | true | Whether to run validation when the property is updated |
$translate | bool | true | Whether to translate validation messages |