Sergej Fomin
Sergej Fomin

Reputation: 2002

Laravel Validating Arrays Select fields

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

Answers (2)

Sergej Fomin
Sergej Fomin

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

omadonex
omadonex

Reputation: 541

public function rules() {
    $rules = [];

    $gender = $this->input('gender');
    foreach ($gender as $index => $item) {
        $rules["gender.{$index}"] = 'required';
    }

    return $rules;
}

Upvotes: 1

Related Questions