Kritim Yantra
Jun 06, 2025
Dynamic forms—where users can add/remove fields on the fly—are essential for surveys, multi-step processes, or complex data entry. Traditionally, this required intricate JavaScript. But with Laravel 12 and Livewire, you can build reactive, dynamic forms entirely in PHP. No Alpine.js, no Vue, no JS fatigue. Let’s create one together.
laravel new dynamic-forms-demo
composer require livewire/livewire
Generate a ContactForm
component:
php artisan make:livewire ContactForm
This creates:
app/Livewire/ContactForm.php
resources/views/livewire/contact-form.blade.php
Goal: Let users add/remove multiple email fields.
app/Livewire/ContactForm.php
<?php
namespace App\Livewire;
use Livewire\Component;
class ContactForm extends Component
{
public $emails = ['']; // Start with one empty email field
// Add a new empty email field
public function addEmail()
{
$this->emails[] = '';
}
// Remove an email field by index
public function removeEmail($index)
{
unset($this->emails[$index]);
$this->emails = array_values($this->emails); // Reindex array
}
// Submit the form
public function submit()
{
// Validate emails (simplified example)
$validated = $this->validate([
'emails.*' => 'required|email',
]);
// Process data (e.g., save to database)
// session()->flash('message', 'Emails saved!');
}
public function render()
{
return view('livewire.contact-form');
}
}
Edit resources/views/livewire/contact-form.blade.php
:
<div class="max-w-2xl mx-auto p-6 bg-white shadow-lg rounded-lg">
<form wire:submit.prevent="submit">
<h2 class="text-2xl font-bold mb-6">Contact Emails</h2>
<!-- Dynamic Email Fields -->
@foreach ($emails as $index => $email)
<div class="flex gap-3 mb-4" wire:key="email-{{ $index }}">
<input
type="email"
wire:model="emails.{{ $index }}"
placeholder="user@example.com"
class="w-full p-3 border rounded-lg focus:ring-2 focus:ring-blue-500"
>
@if ($index > 0)
<button
type="button"
wire:click="removeEmail({{ $index }})"
class="px-4 bg-red-500 text-white rounded-lg hover:bg-red-600"
>
Remove
</button>
@endif
</div>
@endforeach
<!-- Add Email Button -->
<button
type="button"
wire:click="addEmail"
class="mb-6 px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600"
>
+ Add Another Email
</button>
<!-- Submit Button -->
<button
type="submit"
class="w-full py-3 bg-green-600 text-white rounded-lg hover:bg-green-700"
>
Save Emails
</button>
</form>
</div>
Edit routes/web.php
:
use App\Livewire\ContactForm;
Route::get('/contact', ContactForm::class);
wire:model
: Binds input values to Livewire’s PHP properties (synced automatically). wire:click
: Calls PHP methods like addEmail()
/removeEmail()
when clicked. wire:submit.prevent
: Prevents default form submission; uses submit()
method instead. $emails
changes, updating the UI.Enhance submit()
with real-time validation:
public function submit()
{
$this->validate([
'emails.*' => 'required|email',
], [
'emails.*.required' => 'Each email field is required.',
'emails.*.email' => 'Enter a valid email address.',
]);
// Save data...
session()->flash('success', 'Emails saved successfully!');
}
Display errors in Blade:
@error('emails.' . $index)
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
@enderror
With Laravel 12 + Livewire, you’ve built a dynamic form that:
✅ Adds/removes fields reactively,
✅ Validates data in real-time,
✅ Requires zero custom JavaScript.
This is the power of Livewire: complex frontend interactions, written entirely in Laravel. No more context-switching between PHP and JS. Focus on your app’s logic—not the glue code.
Embrace the simplicity. Happy coding! 🚀
Transform from beginner to Laravel expert with our personalized Coaching Class starting June 14, 2025. Limited enrollment ensures focused attention.
1-hour personalized coaching
Build portfolio applications
Industry-standard techniques
Interview prep & job guidance
Complete your application to secure your spot
Thank you for your interest in our Laravel mentorship program. We'll contact you within 24 hours with next steps.
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google