Aug 31, 2023
0
Level 6
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.
Please or to participate in this conversation.