I'm trying to validate only two fields at the same time if any of them is updated, but it seems "ValidatesInput::validateOnly()" is only validating the first field. Below is part of my code:
Component:
public $houseNumber;
public $poleNumber;
protected $rules = [
'houseNumber' => 'required_without:poleNumber|integer|numeric|nullable',
'poleNumber' => 'required_without:houseNumber|integer|numeric|nullable'
];
public function updated($field){
if (in_array($campo, ["houseNumber", "poleNumber"])) {
$this->validateOnly("houseNumber");
$this->validateOnly("poleNumber");
} else {
$this->validateOnly($field);
}
}
I realized I only have a problem if the first validation throws an error, as it stops and shows the error message for the "houseNumber" field only, in this case. How could I make it show for both fields without using "ValidatesInput::validate()"?
public function updated($field)
{
if (in_array($campo, ["houseNumber", "poleNumber"])) {
$this->withValidator(function (Validator $validator) {
if ($validator->fails()) {
$this->addError("poleNumber", "Pole Number* or House Number* field is mandatory.");
$this->addError("houseNumber", "House Number* or Pole Number* field is mandatory.");
}
})->validateOnly($field);
if ($campo == "houseNumber") {
$this->validateOnly("poleNumber");
} else {
$this->validateOnly("houseNumber");
}
} else {
$this->validateOnly($field);
}
}
You have a field on the page that, based on its value, alters validation rules for other fields. So when a change is made to that field you may want to validate only the affected fields; multiple fields but not all fields.
I've run into this issue a few times now and still wish there were a validateMultiple or that validateOnly could take an array.
I still need to test the hell out of it but so far this prototype trait seems to be holding up surprisingly well. It runs through each field individually and builds up a composite ValidationException to throw. The visual messages are updating accordingly without affecting those of other fields.
<?php
namespace App\Livewire\Concerns;
use Illuminate\Support\MessageBag;
use Illuminate\Validation\ValidationException;
use function Livewire\invade;
trait WithValidateMultiple
{
public function validateMultiple($fields, $rules = null, $messages = [], $attributes = []) : array
{
$bag = new MessageBag;
$failedRules = [];
$validated = [];
foreach ($fields as $field) {
try {
$result = $this->validateOnly($field, $rules, $messages, $attributes);
$validated = array_merge($validated, $result);
} catch (ValidationException $e) {
$bag->merge(invade($e->validator)->messages);
$failedRules = array_merge_recursive($failedRules, invade($e->validator)->failedRules);
}
}
if ($bag->any()) {
$exception = ValidationException::withMessages($bag->getMessages());
invade($exception->validator)->failedRules = $failedRules;
throw $exception;
}
return $validated;
}
}