Reputation: 2002
Laravel easily validates array based form input fields
<input name='input_name[0][0]">
<input name='input_name[0][1]">
with
'input_name.* = 'required',
https://laravel.com/docs/5.5/validation#validating-arrays
But how can I validate array based select fields?
I have a form where customer info is added, user has to choose the customer's gender and it's possible to add infinite number of customer.
So i have a select for 1 customer:
<select name="gender[0]">
<option selected="selected" disabled="disabled" hidden="hidden" value="">Gender</option>
<option value="Male">Male</option>
<option value="Female">Female</option></select>
and then
<select name="gender[1]">...
<select name="gender[N]">
When I set the rule as:
'gender.*' => 'required'
It doesn't recognize an 'unchoosen' select-box as an error....
But if I update validation rules to:
'gender[0]'=>'required'
'gender[1]'=>'required'
'gender[N]'=>'required'
It works absolutely fine... (by "it works", I mean that it returns a mistake "Gender field is required").
So, apparently Laravel has some problems with array based select names.
Appreciate any help!
Upvotes: 1
Views: 1560
Reputation: 2002
I've decided o answer the question myself.
1) First solution is to make the first "placeholder" option not disabled (as was in my case, see above - it's because I use LaravelCollective and they have it by default):
<select name="gender[0]">
<option selected="selected" hidden="hidden" value="">Gender</option>
<option value="Male">Male</option>
<option value="Female">Female</option></select>
When you remove 'disabled' from option-1 of your select then it sends ' ' when posting (instead of sending nothing with 'disabled'). So it sends
gender[0] = '';
gender[1] = '';
etc...
Actually, if you have a lot of gender[N]
(or maybe other array based selects) I think it's the neatest solution.
2) Second solution is provided below by omadonex:
public function rules() {
$rules = [];
$gender = $this->input('gender');
foreach ($gender as $index => $item) {
$rules["gender.{$index}"] = 'required';
}
return $rules;
}
in this case you'll have a separate rule for every array-based select and it will work (see why in the end of my topicstarter-post). I prefer this solution less than 1st one because you'll have a long list of "gender"-rules if you have a lot of ...
3) Also I've undertood why 'gender[0]'=>'required'
works
and 'gender.*' => 'required'
does not
for array based selects like <select name=gender[0]>
It's kind of obvious if you think about it: when POSTING select tag with first option (a placeholder) being disabled, as in my example above:
<option selected="selected" disabled="disabled" hidden="hidden" value="">Gender</option>
the $POST sends nothing....
So if Laravel's validation rule is 'gender[0]'=>'required'
Laravel "thinks": "OKAY, I've received no "gender[0]"
, but I know what is required exactly ("gender[0]"
, of course) . I have to send a mistake because there is no "gender[0]"
.
But if rule is 'gender.*' => 'required'
and Laravel get's no input of "gender" kind, then it also doesn't know what EXACTLY is required ('gender.*'
may mean gender[0]
... gender [12345]
... gender[anything]
). Laravel can't send a mistake, because infinite number of gender[...]
is missing, so he simply omits it....
PS. If you work with LaravelCollective forms of newer versions, they create placeholder "disabled" by default. Here is a macro to avoid it.
{!!
Form::macro('selectNonDisabled', function($value, $placeholder, $array, $disabled=null, $class=null) {
$select = "<select class='form-control $class' $disabled name='$value'>";
$select .= "<option selected='selected' hidden='hidden' value=''>$placeholder</option>";
foreach ($array as $key => $value) {
$select .= "<option value='$key'>$value</option>";
}
$select .= "</select>";
return $select;
});
!!}
Upvotes: 1
Reputation: 541
public function rules() {
$rules = [];
$gender = $this->input('gender');
foreach ($gender as $index => $item) {
$rules["gender.{$index}"] = 'required';
}
return $rules;
}
Upvotes: 1