I am trying to build a dynamic form for a warehouse management portal using Laravel and Livewire. For that form I need validation for all the input values. I have followed the exact format given in this blog post Dynamic Form Laravel. I have double checked my code and even used AI tools like ChatGPT to check whether the code logic is correct or not. But still the validation for the nested values do not work. I am uploading my blade file and livewire component.
Blade File:
<div>
{{-- Alert Box--}}
<div>
@if (session()->has('message'))
@if(session('message')=='added')
<div class="alert alert-success">
{{'Data Added Successfully!'}}
</div>
@elseif(session('message')=='updated')
<div class="alert alert-warning">
{{'Data Updated Successfully!'}}
</div>
@else
<div class="alert alert-danger">
{{'Data Was Not Added/Updated!!'}}
</div>
@endif
@endif
</div>
{{-- Form to add the part--}}
<form wire:submit.prevent="add" enctype="multipart/form-data">
@csrf
<div class="flex flex-col mt-2 md:flex-row">
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="salesPartNo">
Sales Part No
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="salesPartNo" type="text" wire:model="sales_part_no">
@error('sales_part_no')
<p class="text-red-500 text-xs italic">{{ $message }}</p>
@enderror
</div>
</div>
<hr>
<!-- Manufacturing Details Section -->
<div class="flex justify-content-between align-items-center">
<p class="text-lg font-bold">Manufacturing Details</p>
<button type="button"
class="cursor-pointer bg-gray-700 py-2 text-white hover:bg-gray-800 hover:text-white focus:ring-4 focus:outline-none focus:ring-blue-300 rounded-md m-2 col-sm-3 w-30p"
wire:click="addManufacturingPart({{$index}})">
Add New Manufacturing Part
</button>
</div>
<!-- First manufacturing part -->
<div class="flex flex-col mt-2 md:flex-row">
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="manufacturingPartNo_0">
Manufacturing Part No
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="manufacturingPartNo_0" type="text" wire:model ="manufacturing_part_no.0">
@error('manufacturing_part_no.0')
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
</div>
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="type_0">
Type
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="type_0" list="types" type="text" wire:model ="type.0">
@error('type.0')
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
<div class="absolute z-10 list-group bg-white rounded-t-none shadow-sm w-25">
<datalist id="types">
@foreach($types as $type)
<option>{{$type}}</option>
@endforeach
</datalist>
</div>
</div>
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="qty_0">
QTY
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="qty_0" type="number" wire:model ="qty.0">
@error('qty.0')
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
</div>
</div>
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="rawMaterialCode_0">
Hex Code/ Forging Die Code
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="rawMaterialCode_0" list="rawMaterialCodes" type="text" wire:model ="raw_material_code.0">
@error('raw_material_code.0')
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
<div class="absolute z-10 list-group bg-white rounded-t-none shadow-sm w-25">
<datalist id="rawMaterialCodes">
@foreach($rawMaterialCodes as $rawMaterialCode)
<option>{{$rawMaterialCode->raw_material_code}}</option>
@endforeach
</datalist>
</div>
</div>
<div class="flex flex-col mt-2 md:flex-row">
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="length_0">
Length of Finished Part in MM
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="length_0" type="number" step="0.01" wire:model ="length.0">
@error('length.0')
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
</div>
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="weightRaw_0">
Weight Of Raw Piece in Kg
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="weightRaw_0" type="number" step="0.001" wire:model ="weight_raw.0">
@error('weight_raw.0')
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
</div>
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="weightFinished_0">
Weight Of Finished Piece in Kg
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="weightFinished_0" type="number" step="0.001" wire:model ="weight_finished.0">
@error('weight_finished.0')
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
</div>
</div>
<!-- Loop through manufacturing_part_indices array -->
@foreach($manufacturing_part_indices as $key=>$manufacturingPartIndex )
<div class="flex flex-col mt-2 md:flex-row">
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="manufacturingPartNo_{{$manufacturingPartIndex}}">
Manufacturing Part No
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="manufacturingPartNo_{{$manufacturingPartIndex}}" type="text"
wire:model ="manufacturing_part_no.{{$manufacturingPartIndex}}">
@error('manufacturing_part_no.*')
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
</div>{{gettype($manufacturingPartIndex)}}
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="type_{{$manufacturingPartIndex}}">
Type
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="type_{{$manufacturingPartIndex}}" type="text" list="types"
wire:model ="type.{{$manufacturingPartIndex}}">
@error('type.'.$manufacturingPartIndex)
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
</div>
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="qty_{{$manufacturingPartIndex}}">
QTY
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="qty_{{$manufacturingPartIndex}}" type="number"
wire:model ="qty.{{$manufacturingPartIndex}}">
@error('qty.'.$manufacturingPartIndex)
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
</div>
</div>
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="rawMaterialCode_{{$manufacturingPartIndex}}">
Hex Code/ Forging Die Code
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="rawMaterialCode_{{$manufacturingPartIndex}}" type="text" list="rawMaterialCodes"
wire:model ="raw_material_code.{{$manufacturingPartIndex}}">
@error('raw_material_code.'.$manufacturingPartIndex)
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
</div>
<div class="flex flex-col mt-2 md:flex-row">
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="length_{{$manufacturingPartIndex}}">
Length of Finished Part in MM
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="length_{{$manufacturingPartIndex}}" type="text"
wire:model ="length.{{$manufacturingPartIndex}}">
@error('length.'.$manufacturingPartIndex)
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
</div>
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="weightRaw_{{$manufacturingPartIndex}}">
Weight Of Raw Piece in Kg
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="weightRaw_{{$manufacturingPartIndex}}" type="text"
wire:model ="weight_raw.{{$manufacturingPartIndex}}">
@error('weight_raw.'.$manufacturingPartIndex)
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
</div>
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="weightFinished_{{$manufacturingPartIndex}}">
Weight Of Finished Piece in Kg
</label>
<input
class="appearance-none block w-full bg-white text-gray-700 border border-gray-200 rounded px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="weightFinished_{{$manufacturingPartIndex}}" type="text"
wire:model ="weight_finished.{{$manufacturingPartIndex}}">
@error('weight_finished.'.$manufacturingPartIndex)
<p class="text-red-500 p-1 text-xs italic">{{ $message }}</p>
@enderror
</div>
<div class="w-full px-3 mb-6 md:mb-6">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
for="remove">
</label>
<button type="button"
class="btn btn-outline-danger m-2 w-full"
wire:click="removeManufacturingPart({{$key}})">
Remove
</button>
</div>
</div>
@endforeach
<div class="px-2 pb-3 sm:px-4 flex justify-content-between mt-2">
<button type="submit"
class="cursor-pointer bg-green-700 py-2 text-white hover:bg-green-800 hover:text-white focus:ring-4 focus:outline-none focus:ring-blue-300 rounded-md m-2 col-sm-3 w-30p"
>Save</button>
<button type="button" class="btn btn-outline-secondary m-2 col-sm-3 w-30p">
Cancel
</button>
</div>
</form>
</div>
Livewire Component:
<?php
namespace App\Http\Livewire\Parts;
use App\Models\BillOfMaterials;
use App\Models\PartManufacturingDetails;
use App\Models\RawMaterial;
use Illuminate\Validation\Rule;
use Livewire\Component;
class AddNewPart extends Component
{
public $sales_part_no;
public $manufacturing_part_no;
public $type;
public $qty;
public $raw_material_code;
public $length;
public $weight_raw;
public $weight_finished;
public $manufacturing_part_indices = [];
public $index = 0;
public $result = [];
public function addManufacturingPart($index)
{
$index = $index + 1;
$this->index = $index;
$this->manufacturing_part_indices[] = $index;
}
public function removeManufacturingPart($index)
{
unset($this->manufacturing_part_indices[$index]);
}
public function resetFields()
{
$this->sales_part_no = null;
$this->manufacturing_part_no = null;
$this->type = null;
$this->qty = null;
$this->raw_material_code = null;
$this->length = null;
$this->weight_raw = null;
$this->weight_finished = null;
}
public function add()
{
//MHH 2023-08-5, Sat, 12:48::Validations of the fields
$messages = [
'required' => 'This field is required.',
'exists' => 'Incorrect Input- :input does not exist in the database',
];
$validatedData = $this->validate([
'sales_part_no' => 'required',
'manufacturing_part_no.0' => 'required',
'type.0' => ['required', Rule::exists('bill_of_materials', 'type')],
'qty.0' => 'required',
'raw_material_code.0' => ['required', Rule::exists('raw_material', 'raw_material_code')],
'length.0' => 'required',
'weight_raw.0' => 'required',
'weight_finished.0' => 'required',
'manufacturing_part_no.*' => 'required',
'type.*' => ['required', Rule::exists('bill_of_materials', 'type')],
'qty.*' => 'required',
'raw_material_code.*' => ['required', Rule::exists('raw_material', 'raw_material_code')],
'length.*' => 'required',
'weight_raw.*' => 'required',
'weight_finished.*' => 'required',
], $messages);
//MHH 2023-08-5, Sat, 12:48::Inserting Data in the database tables
foreach ($this->manufacturing_part_no as $index => $value) {
if (in_array($index, $this->manufacturing_part_indices) || $index == 0) {
PartManufacturingDetails::create([
'manufacturing_part_no' => $this->manufacturing_part_no[$index],
'raw_material_code' => $this->raw_material_code[$index],
'length' => $this->length[$index],
'weight_raw' => $this->weight_raw[$index],
'weight_finished' => $this->weight_finished[$index]
]);
BillOfMaterials::create([
'sales_part_no' => $this->sales_part_no,
'manufacturing_part_no' => $this->manufacturing_part_no[$index],
'type' => $this->type[$index],
'qty' => $this->qty[$index]
]);
}
}
//MHH 2023-08-5, Sat, 12:47:: Resetting all the fields
$this->manufacturing_part_indices = [];
$this->resetFields();
//MHH 2023-08-5, Sat, 12:47::Send Flash Message
session()->flash('message', 'added');
}
public function render()
{
return view('livewire.parts.add-new-part',[
'types' => BillOfMaterials::distinct()->pluck('type'),
'rawMaterialCodes' => RawMaterial::select('raw_material_code')->get()
]);
}
}
This is what I get when I use dd() to get the $validatedData array: dd($validatedData)
What am I missing here? Any help will be really appreciated.. Thank you..
I have tried removing the first manufacturing part which will have the index 0 so the array is sequential which it is in either way. It still did not work.