How to create Dynamic Rows with Input Fields in Laravel Livewire

Using Laravel Livewire to implement “How to create Dynamic Rows with Input Fields in Laravel Livewire” provides a more dynamic and reactive user experience. Below is a complete solution for your requirement in Laravel Livewire.

Step 1: Create a Livewire Component

Run the following command to create a Livewire component:


php artisan make:livewire SubjectForm

Step 2: Update the Livewire Component Class

Edit the generated SubjectForm.php file in app/Http/Livewire.


namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Subject;

class SubjectForm extends Component
{
public $subjects = [
['subject_name' => '', 'minimum_marks' => '', 'type' => '']
];

public function addRow()
{
$this->subjects[] = ['subject_name' => '', 'minimum_marks' => '', 'type' => ''];
}

public function removeRow($index)
{
unset($this->subjects[$index]);
$this->subjects = array_values($this->subjects); // Reindex the array
}

public function save()
{
$this->validate([
'subjects.*.subject_name' => 'required|string',
'subjects.*.minimum_marks' => 'required|integer',
'subjects.*.type' => 'required|string|in:Fix,%,Grade',
]);

foreach ($this->subjects as $subject) {
Subject::create($subject);
}

session()->flash('success', 'Subjects saved successfully!');
$this->reset('subjects');
$this->subjects = [
['subject_name' => '', 'minimum_marks' => '', 'type' => '']
];
}

public function render()
{
return view('livewire.subject-form');
}
}

Step 3: Create the Blade View for the Component

Edit the subject-form.blade.php file in resources/views/livewire.


<div>
@if (session()->has('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif

<form wire:submit.prevent="save">
<table class="table table-bordered">
<thead>
<tr>
<th>Subject Name</th>
<th>Minimum Marks</th>
<th>Type</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@foreach ($subjects as $index => $subject)
<tr>
<td>
<input type="text" class="form-control" wire:model="subjects.{{ $index }}.subject_name" required />
@error("subjects.{$index}.subject_name") <span class="text-danger">{{ $message }}</span> @enderror
</td>
<td>
<input type="number" class="form-control" wire:model="subjects.{{ $index }}.minimum_marks" required />
@error("subjects.{$index}.minimum_marks") <span class="text-danger">{{ $message }}</span> @enderror
</td>
<td>
<select class="form-control" wire:model="subjects.{{ $index }}.type" required>
<option value="" disabled>Select</option>
<option value="Fix">Fix</option>
<option value="%">%</option>
<option value="Grade">Grade</option>
</select>
@error("subjects.{$index}.type") <span class="text-danger">{{ $message }}</span> @enderror
</td>
<td>
<button type="button" class="btn btn-danger" wire:click="removeRow({{ $index }})">X</button>
</td>
</tr>
@endforeach
</tbody>
</table>

<button type="button" class="btn btn-primary" wire:click="addRow">Add More</button>
<button type="submit" class="btn btn-success">Submit</button>
</form>
</div>

Step 4: Update the Subject Model

Ensure the Subject model is set up with the correct fillable fields.


namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Subject extends Model
{
use HasFactory;

protected $fillable = ['subject_name', 'minimum_marks', 'type'];
}

Step 5: Update the Migration

Ensure your database table is properly set up. For example:


use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateSubjectsTable extends Migration
{
public function up()
{
Schema::create('subjects', function (Blueprint $table) {
$table->id();
$table->string('subject_name');
$table->integer('minimum_marks');
$table->enum('type', ['Fix', '%', 'Grade']);
$table->timestamps();
});
}

public function down()
{
Schema::dropIfExists('subjects');
}
}

Step 6: Add the Component to a Blade File

Include the Livewire component in your desired Blade file:


<livewire:subject-form />

Step 7: Configure Routes

Ensure Livewire’s JavaScript is included in your layout, and the routes are properly configured.

Add this to your layout’s <head> section:


@livewireStyles
@livewireScripts

Add the Livewire component route:
Route::get('/subjects', \App\Http\Livewire\SubjectForm::class)->name('subjects');
This Livewire-based solution allows dynamic row addition and deletion with real-time validation and submission.

Leave a Comment