Livewire dynamic file upload
I have to develop a file upload using Livewire where users can select multiple files and upload. When a user selects multiple files, each file should be listed down with a drop down and text area. In the dropdown, the type of file should be selected. Then an optional comment can be added. All the files are required to be uploaded. And each file type can only have one file assigned to it. I have tried doing this in the following way but struggling with some parts like validating files with each file type.
First, I create two arrays to store uploaded files. Then I try to make the $documents array as I needed.
public array $uploadedDocuments = [];
public array $documents = [
// [
// 'label' => 'front view',
// 'comment' => 'new comment',
// 'file' => (new TemporaryUploadedFile),
// ],
// [
// 'label' => 'back view',
// 'comment' => 'new comment',
// 'file' => (new TemporaryUploadedFile),
// ],
// [
// 'label' => 'top view',
// 'comment' => 'new comment',
// 'file' => (new TemporaryUploadedFile),
// ],
];
Then I use Livewire's lifecycle hook to merge the two arrays and make the $documents array as I needed.
public function updatedUploadedDocuments()
{
//append the new documents to the uploaded documents array
$this->documents = array_merge(array_column($this->documents, 'file') ?? [], $this->uploadedDocuments);
$this->documents = collect($this->documents)->map(fn($file) => ['label' => rand(1,11), 'comment' => '', 'file' => $file])->all();
}
This is how I validate the data.
$this->validate([
'documents' => 'required|array|min:10|max:11',
'documents.*' => 'required|array',
'documents.*.file' => 'required|file|max:2048',
'documents.*.label' => ['required','numeric',function ($value,$attribute,$fail) {
if(collect($this->documents)->duplicates()->count() > 0){
$fail('Label should only use once.');
}
}],
'documents.*.comment' => 'nullable'
]);
Code inside blade file
@if(isset($documents))
@foreach($documents as $index => $document)
<div class="mb-3">
<h3>{{ $loop->iteration }}</h3>
@if($document['file']->isPreviewable())
<img src="{{ $document['file']->temporaryUrl() }}" alt="image" width="100">
@else
<i class="fas fa-file fa-3x"></i>
@endif
<select class="form-select" aria-label="Default select example"
wire:model="documents.{{ $index }}.label">
<option selected>Open this select menu</option>
<option value="1">CR Copy</option>
<option value="2">Front View</option>
<option value="3">Rear View</option>
<option value="4">Left Side View</option>
<option value="5">Right Side View</option>
<option value="6">Body Tag</option>
<option value="7">ODO Meter</option>
<option value="8">Customer Selfie</option>
<option value="9">Officer Selfie</option>
<option value="10">VIN Number</option>
<option value="11">Engine Number</option>
</select>
<textarea wire:model="documents.{{ $index }}.comment" name="" id=""></textarea>
</div>
@endforeach
@endif
How can I properly do this? TIA!
Please or to participate in this conversation.