0

I'm wanting to be able to split my laravel error messaged into sections.

Lets say I have an insurance policy page that has 3 sections

Driver Details

Car Details

Policy Details

I'm using a laravel request like this

'driver_name' => 'required',
'address_line_1' => 'required',
'address_line_2' => 'required',
'address_line_3' => 'required',
'postcode' => 'required',

I want to be able to tag certain input errors when validating with an input request like this so that I can display an error message at the top of each section, instead of 1 giant error block with all the errors in it.

In the request, how would i send it back with a section tag like

'driver_name' => 'required|section:driverDetails'

To split the errors?

If laravel error messages cant be tagged, what would be the best practise to achieve this?

S_R
  • 1,818
  • 4
  • 27
  • 63
  • Write some custom validator functions for each section, I guess. Then figure out a way to find out which section a request belongs to and pass the request to the correct validator function. – Loek Jul 04 '18 at 14:20
  • Validation is a different concern than presentation so you probably need to write code to manually put the errors in "buckets" – apokryfos Jul 04 '18 at 15:48
  • Group your inputs, i.e. ``. – Martin Bean Jul 04 '18 at 15:54

2 Answers2

2

You can use Vue.js and axios to validate and display the errors. Have a route called /validate-data in a controller to validate the data.

app.js file:

       import Vue           from 'vue'
        window.Vue = require('vue');
        window.axios = require('axios');

        window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

        let token = document.head.querySelector('meta[name="csrf-token"]');

        if (token) {
            window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
        } else {
            console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
        }

             class Errors {
                constructor() {
                    this.errors = {};
                }

                get(field) {
                    if (this.errors[field]) {

                        return this.errors[field][0];
                    }
                }

                record(errors) {
                    this.errors = errors;
                }

                clear(field) {
                    delete this.errors[field];
                }

                has(field) {
                    return this.errors.hasOwnProperty(field);
                }

                any() {
                    return Object.keys(this.errors).length > 0;
                }
            }

            new Vue({
             el: '#app',

                data:{
               errors: new Errors(),
              model: {
    driver_name: '',
    address_line1: '',
    address_line2: ''
    },
            },

        methods: {
          onComplete: function(){
              axios.post('/validate-data', this.$data.model)
                  // .then(this.onSuccess)
                  .catch(error => this.errors.record(error.response.data.errors));
           },
}
        });

Make a route called /validate-data with a method in the controller, do a standard validate

$this->validate(request(), [
'driver_name' => 'required',
'address_line_1' => 'required',
'address_line_2' => 'required',
'address_line_3' => 'required',
'postcode' => 'required'
]

Then create your inputs in your view file, using v-model that corresponds to the vue.js data model fields. Underneath it, add a span with an error class (basic red error styling, for example) that only shows up if the errors exist. For example:

<input type="text" name="driver_name" v-model="model.driver_name" class="input">
<span class="error-text" v-if="errors.has('driver_name')" v-text="errors.get('driver_name')"></span>

Don't forget to include the app.js file in footer of your view file. Remember to include the tag, and run npm run watch to compile the vue code. This will allow you to validate all errors underneath their input fields.

Forgot to add, have a buttton that has @onclick="onComplete" to run the validate method.

CupOfSalt
  • 55
  • 8
0

You can get $errors for each validation rule So, if you have next rule:

'driver_name' => 'required',

You simply can output error on top of driver_name field in your blade

@if ($errors->has('driver_name'))
    <div class="error">{{ $errors->first('driver_name') }}</div>
@endif
<input type="text" name="driver_name">

You can refer to the docs here

  • Thank you for your suggestion, but I am not looking list each error and check if its set, I would like to be able to have 1 piece of code run and figure out where to place the errors – S_R Jul 04 '18 at 14:41
  • i`m not sure that is possible. at least I did not meet stuff like that – Yura Halias Jul 04 '18 at 14:44