Laravel custom validation message for wildcard (*) dot notation

Viewed 1614

When defining validation for lets say form elements that have the same array name, we use the wildcard (*) dot-notation

Lets say you have a form as shown:

<input type="text" name="client_type[]" class="form-control" value="Panelist" readonly>
<input type="number" name="commission_percentage[]" class="form-control">

<input type="text" name="client_type[]" class="form-control" value="Non Panelist" readonly>
<input type="number" name="commission_percentage[]" class="form-control">

Inorder to validate the commission_percentage field, we would do this in a form request class:

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

   $rules['commission_percentage.*'] = 'required';

   return $rules;
}

From the form above, submitting it while empty would generate the following validation error message:

The commission_percentage.0 field is required. 
The commission_percentage.1 field is required

The validation error message would be repeated twice since the commission_percentage array from the form has 2 values. Now imagine a case where the array has multiple values, the validation error message would be repeated each and every time!

So the question is: Is there a workaround for this so that instead of the validation error message being repeated n number of times, we have one validation error message that will be output and represent all the items in the same array?

Thanks.

3 Answers

I think you can override the messages method in your form request and add a single message, for example:

public function messages()
{
    return [
        'commission_percentage.*' => 'Your field is required'
    ];
}

Then to use it in the view you should exclude it from the $errors->any() loop but to get it as a single error like this:

@if ($errors->has('commission_percentage.*'))
    <div class="help-block">
        <ul role="alert">
           <li>{{ $errors->first('commission_percentage.*') }}</li>
        </ul>
    </div>
@endif

So @nakov's answer above inspired this solution:

I'm using ajax to post my form. To avoid the +n validation error messages for values of the same array:

$.ajax({
        url: postUrl,
        type: 'POST',
        data: formData,
        cache: false,
        contentType: false,
        processData: false
    })
    .done(function( data ) {
     //
    })
    .fail(function(data) {
        if( data.status === 422 ) 
        {
            var errorResponse = JSON.parse(data.responseText);

            var errors= '';
            errors += '<ul>';
            var commissionError = '';

            $.each( errorResponse.errors, function( key, value ) {       


                if (key.indexOf('commission_percentage') > -1)
                {
                    commissionError  = value;

                }
                else
                {
                    errors += '<li>' + value + '</li>';
                }
            });

            commissionError = '<li>' + commissionError + '</li>';
            errors = errors + commissionError;
            errors += '</ul>';

            $('#role-errors').children('.alert').html(errors).css({ 'display':'block', 'padding': '1rem' });
        }

So, i defined commissionError variable, checked for the existence of the commission_percentage key, as defined in my form request rule, capture the values that match and display it outside my loop as such:

commissionError = '<li>' + commissionError + '</li>';

Then concatenate to the main errors string as shown:

errors = errors + commissionError;

And that's it! Now all the required attributes under the commission_percentage are represented by a single validation error message. Neat!

If you have all your error messages grouped in one place in your view, you may use the unique method instead of all, for example:

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->unique() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

Providing you specified a custom message for the rule like in @nakov answer:

public function messages()
{
    return [
        'commission_percentage.*.required' => 'Your field is required'
    ];
}
Related