Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ctyler's avatar

Livewire Autosuggest on Dynamic form Fields

I am working on purchase request application. Users can dynamic add and remove line items to the request before submitting. That part is working as expected.

I would like the ability to add an auto suggest to each line item. Here is what I have now:

Component

class CreatePurchaseRequest extends Component
{
    use WithFileUploads;
    public $updateMode = false;

    public $inputs = [];

    public $i = 0;

    public $units = [];
    public $itemName = [];

    public $description = [];
    public $purchaseRequestType;
    public $selectedPurchaseRequestType;
    public $dateNeeded = '';
    public $responsibleOrganization;
    public $selectedResponsibleOrganization;

    public $specialInstructions;

    public $additionalDocs = [];

    protected $rules = [

        'selectedPurchaseRequestType' => ['required'],
        'selectedResponsibleOrganization' => ['required'],
        'dateNeeded' => ['required', 'date', 'date_format:m/d/Y', 'after:today'],
        'units.0' => ['required'],
        'itemName.0' => ['required'],
        'description.0' => ['sometimes'],
        'units.*' => ['required'],
        'itemName.*' => ['required'],
        'description.*' => ['sometimes'],

    ];



    protected $messages = [

        'selectedPurchaseRequestType' => 'You must select a request type.',
        'selectedResponsibleOrganization' => 'You must select a responsible organization.',

    ];
    public function mount()
    {
        $this->purchaseRequestType = PurchaseRequestType::orderBy('name')
            ->get()->toArray();
        $this->responsibleOrganization = PurchaseRequestResponsibleOrganization::orderBy('name')
            ->get()->toArray();

    }

    public function add($i)

    {
        $i = $i + 1;
        $this->i = $i;
        array_push($this->inputs ,$i);
    }

    public function remove($i)

    {

        unset($this->inputs[$i]);

    }

    private function resetInputFields(){

        $this->units = '';
        $this->itemName = '';
        $this->description = '';

    }




    public function submitPurchaseRequest()
    {
        $validatedData = $this->validate([
            'purchaseRequestType' => ['required'],
            'dateNeeded' => ['required']
            ]);
    }

    public function render()
    {
        return view('livewire.purchasing.purchase-request.create-purchase-request');
    }
}

Blade

<div>
    <form wire:submit.prevent="submitPurchaseRequest">
        <div class="row">
            <div class="col-md-3">
                <div class="mb-3">
                    <label for="select-type" class="form-label">Purchase request type:</label>
                    <select
                            wire:model="selectedPurchaseRequestType"
                            name="type"
                            class="form-select" id="purchaseRequestType"
                    >
                        <option value="" selected>Please select a type</option>

                        @foreach($purchaseRequestType as $type)
                            <option value="{{$type['id']}}">{{$type['name']}}</option>
                        @endforeach
                    </select>
                    @error('category')
                    <p class="text-danger">{{ $message }}</p>
                    @enderror
                </div>
            </div>
            <div class="col-md-3">
                <div class="mb-3">
                    <label for="min_create_date" class="form-label">Date needed by:</label>
                    <div
                            x-data="{ value: @entangle('dateNeeded'), picker: undefined }"
                            x-init="new Pikaday({ field: $refs.input, format: 'MM/DD/YYYY', onOpen() { this.setDate($refs.input.value) } })"
                            x-on:change="value = $event.target.value"

                            class="input-group mb-3"

                    >
                        <span class="input-group-text"><i class="fa fa-calendar-alt"></i></span>
                        <input
                                x-ref="input"
                                x-bind:value="value"
                                type="text"
                                class="form-control"
                                wire:model="dateNeeded"
                                id="dateNeeded"
                                placeholder="MM/DD/YYYY"
                        >
                    </div>
                    @error('dateNeeded')
                    <p class="text-danger">{{ $message }}</p>
                    @enderror
                </div>
            </div>
            <div class="col-md-3">
                <div class="mb-3">
                    <label for="select-type" class="form-label">Responsible organization:</label>
                    <select
                            wire:model="selectedResponsibleOrganization"
                            name="type"
                            class="form-select" id="purchaseRequestType"
                    >
                        <option value="" selected>Please select a type</option>
                        @foreach($responsibleOrganization as $org)
                            <option value="{{$org['id']}}">{{$org['name']}}</option>
                        @endforeach
                    </select>
                    @error('category')
                    <p class="text-danger">{{ $message }}</p>
                    @enderror
                </div>
            </div>
        </div>
        <div class="add-input">
            <div class="row">
                <div class="col-md">
                    <h4 class="card-header">Add line items</h4>
                </div>
            </div>
            <div class="row">
                <div class="col-md-2">
                    <div class="form-group">
                        <label for="units.0">Quantity</label>
                        <input type="text" class="form-control" wire:model="units.0">
                        @error('units.0') <span class="text-danger error">{{ $message }}</span>@enderror
                    </div>

                </div>
                <div class="col-md-3">
                    <div class="form-group">
                        <label for="itemName.0">Item Name</label>
                        <input type="email" class="form-control" wire:model="itemName.0">
                        @error('itemName.0') <span class="text-danger error">{{ $message }}</span>@enderror
                    </div>
                </div>

                <div class="col-md-3">
                    <div class="form-group">
                        <label for="description.0">Description</label>
                        {{--                        <input type="description" class="form-control" wire:model="description.0">--}}
                        <textarea wire:model="description.0" class="form-control" id="description.0"
                                  rows="2"></textarea>
                        @error('description.0') <span class="text-danger error">{{ $message }}</span>@enderror
                    </div>
                </div>
                <div class="col-md-2">
                    <button class="btn text-white btn-info btn-sm mt-4" wire:click.prevent="add({{$i}})">Add</button>
                </div>
            </div>

        </div>
        @foreach($inputs as $key => $value)
            <div class="add-input">
                <div class="row">
                    <div class="col-md-2">
                        <div class="form-group">
                            <label for="units.0">Quantity</label>
                            <input type="text" class="form-control" wire:model="units.{{ $value }}">
                            @error('units.'.$value) <span class="text-danger error">{{ $message }}</span>@enderror
                        </div>

                    </div>
                    <div class="col-md-3">
                        <div class="form-group">
                            <label for="itemName.0">Item Name</label>
                            <input type="text" class="form-control" wire:model="itemName.{{ $value }}">
                            @error('itemName.'.$value) <span class="text-danger error">{{ $message }}</span>@enderror
                        </div>
                    </div>

                    <div class="col-md-3">
                        <div class="form-group">
                            <label for="description.{{ $value }}">Description</label>
                            {{--                            <input type="description" class="form-control" wire:model="description.{{ $value }}">--}}
                            <textarea wire:model="description.{{ $value }}" class="form-control"
                                      id="description.{{ $value }}" rows="2"></textarea>
                            @error('description.'.$value) <span class="text-danger error">{{ $message }}</span>@enderror
                        </div>
                    </div>
                    <div class="col-md-2">
                        <button class="btn btn-danger btn-sm mt-4" wire:click.prevent="remove({{$key}})">remove</button>
                    </div>
                </div>
            </div>
        @endforeach
        <div class="row">
            <div class="col-md-9">
                <div class="form-group">
                    <label for="specialInstructions">Special instructions</label>
                    {{--                            <input type="description" class="form-control" wire:model="description.{{ $value }}">--}}
                    <textarea wire:model="specialInstructions" class="form-control" id="specialInstructions"
                              rows="2"></textarea>
                    @error('specialInstructions') <span class="text-danger error">{{ $message }}</span>@enderror
                </div>
            </div>
        </div>
        <div class="row">
            @foreach($additionalDocs as $file)
                {{ print_r($file->getClientOriginalName()) }}
            @endforeach
        </div>
        <div class="row">
            <div class="col-md-9">
                <div class="mb-3">
                    <label for="additionalDocs" class="form-label">Additional Documentation</label>
{{--                    <input wire:model="additionalDocs" class="form-control" type="file" id="additionalDocs" multiple>--}}
                    <x-form.input.filepond wire:model="additionalDocs" multiple />
                </div>
            </div>
        </div>
    </form>
</div>

In a typical auto suggest scenario I would just use

public function updatedItemName($value)
{
 $this->items = Itmes::where('name', 'LIKE', '%' . $value . '%')
            ->get()
}

Or something similar to that. Im not sure ho I would handle that when the itemName wire:model is

wire:model="itemName.{{ $value }}"

any suggestions would be appreciated.

0 likes
0 replies

Please or to participate in this conversation.