Hello.
I want to validate a form with multiple fields of type text and file. But when performing the validation it asks me that the file field has the validation of the texts.
The field 2 is of type File but in the error the validation expects it to be one of type text (answer)
component:
<?php
namespace App\Http\Livewire;
use App\Models\Entry;
use App\Models\Form;
use App\Models\Profile;
use App\Notifications\NewOrder;
use Illuminate\Support\Facades\URL;
use Livewire\Component;
use Livewire\WithFileUploads;
class QuestionaryComponent extends Component
{
use WithFileUploads;
protected $listeners = ['showQuestionary', 'closeQuestionary', 'profileSaved'];
public $showQuestionary = false;
public $showProfileForm = false;
public $questionary;
public $profile;
public $rows = [];
protected $rules = [
'rows.*.answer' => 'required|string|max:500',
'rows.*.file.*' => 'required|image',
];
public function showQuestionary(Form $form)
{
$this->showProfileForm = false;
$this->questionary = $form;
$this->rows = $this->questionary
->questions
->map(function($item){
$fields = [
'id' => $item->pivot->id,
'required' => $item->pivot->required,
'name' => $item->name,
'type' => $item->question_type->name,
'description' => $item->description,
'answer' => $item->answer
];
if ('file' == $item->question_type->name)
unset($fields['answer']);
return $fields;
})->keyBy('id')
->toArray();
$this->showQuestionary = true;
}
public function closeQuestionary()
{
$this->reset('rows');
$this->showQuestionary = false;
$this->showProfileForm = false;
}
public function validateQuestionary()
{
$this->validate();
$this->showProfileForm = true;
}
public function save()
{
$this->validate();
$entry = new Entry();
$entry->answers = $this->rows;
$entry->amount = $this->questionary->amount;
$entry->currency = env('CURRENCY');
$entry->form()->associate($this->questionary);
$entry->profile()->associate($this->profile);
$entry->save();
$this->closeQuestionary();
$this->profile->notify(new NewOrder($entry));
session()->flash('success', __('Request created successfully.'));
return redirect( URL::signedRoute('entry', ['entry' => $entry]) );
}
public function profileSaved(Profile $profile)
{
$this->profile = $profile;
$this->save();
}
public function render()
{
return view('livewire.questionary-component');
}
}
View:
<div x-data="{ show : @entangle('showProfileForm') }" class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="absolute bg-white bg-opacity-75 inset-0 z-10" wire:loading>
<div class="w-full h-full flex justify-center items-center">
<div class="animate-spin rounded-full w-10 h-10 border-t-8 border-solid border-red-500"
style="border: 4px solid #bebebe; border-top: 4px solid #0f87d6;"></div>
</div>
</div>
@if ($showQuestionary)
{{-- Header card --}}
<div class="flex flex-col sm:flex-row justify-between px-4 py-5 border-b border-gray-200 sm:px-6">
<div>
<h3 class="text-lg leading-6 font-semibold text-gray-900">
@if (!empty($questionary))
{{ $questionary->name }}
@endif
</h3>
<p class="mt-1 max-w-2xl text-base leading-normal text-gray-500">
@if (!empty($questionary))
{{ $questionary->description }}
@endif
</p>
</div>
<div>
<p class="py-2 sm:text-right flex flex-col">
<span class="font-bold text-green-400 text-lg">
{{ env('CURRENCY_SYMBOL') }}{{ $questionary->amount }}
</span>
@if ($questionary->hasDisccount)
<span class="text-sm line-through text-gray-400">
{{ env('CURRENCY_SYMBOL') }}{{ $questionary->price }}
</span>
@endif
</p>
</div>
</div>
{{-- Body card --}}
<div
x-show="!show"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 transform scale-50"
x-transition:enter-end="opacity-100 transform scale-100"
x-transition:leave="transition ease-in duration-300"
x-transition:leave-start="opacity-100 transform scale-100"
x-transition:leave-end="opacity-0 transform scale-50"
class="px-6 py-5">
<form wire:submit.prevent="save">
@if (session()->has('errors'))
<div class="bg-red-100 border border-red-400 text-red-400 p-2 rounded mb-2">
{{ session('errors') }}
</div>
@endif
<pre>
@php
print_r($rows)
@endphp
</pre>
@error('rows.*') <span class="text-red-500">{{ $message }}</span> @enderror
<div class="grid grid-cols-6 gap-6">
@if ($questionary->questions->count() > 0)
@foreach ($rows as $key => $question)
<div class="col-span-6 sm:col-span-6" wire:key="{{ $question['id'] }}">
<x-jet-label for="{{ $question['id'] }}" value="{{ $question['name'] }}" class="text-base"/>
<p class="p-1 text-base text-gray-400 leading-tight">
{{ $question['description'] }}
</p>
@if ('text' == $question['type'])
<input
wire:model.defer="rows.{{ $question['id'] }}.answer"
class="mt-1 form-input block w-full transition duration-150 ease-in-out sm:text-base sm:leading-5"/>
<x-jet-input-error for="rows.{{ $question['id'] }}.answer" class="mt-2" />
@endif
@if ('textarea' == $question['type'])
<textarea
wire:model="rows.{{ $question['id'] }}.answer"
rows="5"
class="mt-1 form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5">
</textarea>
<x-jet-input-error for="rows.{{ $question['id'] }}.answer" class="mt-2" />
@endif
@if ('file' == $question['type'])
<input
type="file"
wire:model="rows.{{ $question['id'] }}.file">
<x-jet-input-error for="rows.{{ $question['id'] }}.file" class="mt-2" />
@endif
</div>
@endforeach
@else
<div class="col-span-6 sm:col-span-6">
<p class="text-gray-400">{{ __('This form has no questions.') }}</p>
</div>
@endif
</div>
</form>
</div>
<div
x-show="show"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 transform scale-50"
x-transition:enter-end="opacity-100 transform scale-100"
x-transition:leave="transition ease-in duration-300"
x-transition:leave-start="opacity-100 transform scale-100"
x-transition:leave-end="opacity-0 transform scale-50"
class="flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
<livewire:profile.widget/>
</div>
{{-- Footer card --}}
<div x-data="{ profileIsOpen: @entangle('showProfileForm') }" class="px-4 py-3 bg-gray-100 text-right sm:px-6">
<x-jet-button x-show="!profileIsOpen" class="ml-2" wire:click="validateQuestionary" wire:loading.attr="disabled">
{{ __('Continue') }}
</x-jet-button>
<x-jet-button x-show="profileIsOpen" class="ml-2 bg-gray-500" x-on:click="show = false" wire:loading.attr="disabled">
{{ __('Go back') }}
</x-jet-button>
</div>
@endif
</div>
Laravel: 8.0
Livewire: 2.0