0

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.

3
  • What do you mean by "dynamic form"? You mean repeaters or? Commented Aug 7, 2023 at 7:22
  • Yeah repeaters.. Commented Aug 7, 2023 at 11:23
  • In that case you will need to use arrays like "repeater.*.title => 'required|string'" validations for each repeater in your components + don't forget to use wire:key ^^ Good luck Commented Aug 8, 2023 at 8:42

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.