1

I want to ask about validation in Laravel and Vue JS.

Here I use Vue JS separately from Laravel. Then I was confused to use validation from Backend and Frontend or better than just one of them.

In this case at Vue JS I use Vuetify, Vuelidate and Vuex.

I have tried validation on Vuetify using Vuelidate, this is very simple.

But I am confused to choose, Am I just enough to make validation in Vue only? or still Retrieve all error responses that are only sent from Backend.

What makes me confused if I only use validation in Frontend is not everything I can make. For example validation of image types, image sizes, unique data and others.

What I'm afraid of is just validating on Frontend. I have to rebuild and this is very inefficient in my opinion.

This is an example of validation in Vue JS that I have.

<template>
    <v-container
        fluid
        tag="section"
    >
    <v-row
        align="center"
        justify="center"
    >
        <v-col
            cols="12"
        >
            <form>
                <v-text-field
                    class="mb-5"
                    v-model="form.title"
                    :error-messages="errors.title"
                    :counter="10"
                    label="Title"
                    required
                    dense
                    @input="$v.form.title.$touch()"
                    @blur="$v.form.title.$touch()"
                ></v-text-field>
                <quill-editor
                    class="mb-5"
                    v-model="form.content"
                    :options="editorOption"
                ></quill-editor>
                <p class="display-6" v-if="errors.content">{{ errors.content }}</p>
                <v-file-input
                    class="mb-5"
                    :error-messages="errors.image"
                    v-model="form.image"
                    label="File input"
                    chips
                    dense
                    clear-icon
                    @validate-on-blur="$v.form.image.$touch()"
                >
                </v-file-input>

                <v-select
                    class="mb-5"
                    :items="items"
                    label="Category"
                    dense
                    chips
                    counter
                ></v-select>

                <v-text-field
                    class="mb-5"
                    v-model="form.slug"
                    :counter="10"
                    label="Slug"
                    required
                    dense
                    :error-messages="errors.slug"
                    @input="$v.form.slug.$touch()"
                    @blur="$v.form.slug.$touch()"
                ></v-text-field>
                <v-btn class="mr-4" @click="submit">submit</v-btn>
                <v-btn @click="clear">clear</v-btn>
            </form>
        </v-col>
    </v-row>
    </v-container>
</template>

<script>
    // * Package
    import { mapState, mapMutations } from 'vuex'
    import { quillEditor } from 'vue-quill-editor'
    import { validationMixin } from 'vuelidate'
    import { required } from 'vuelidate/lib/validators'

    // * Css
    import 'quill/dist/quill.snow.css'

    export default {
        name: 'Store.Articles',
        components: {
            quillEditor
        },
        mixins: [validationMixin],
        validations: {
            form: {
                title: { required },
                slug: { required }
            }
        },
        data() {
            return {
                editorOption: {
                    placeholder: 'Type your post...',
                    readOnly: true,
                    theme: 'snow'
                },
                items: [
                    'News', 'Promo', 'Maintenance'
                ]
            }
        },
        computed: {
            ...mapState(['errors']),
            ...mapState('article', {
                form: state => state.form
            }),
            titleErrors () {
                if (!this.$v.form.title.$dirty) return errors
                !this.$v.form.title.required && errors.push('Title is required.')
                return errors
            },
            slugErrors () {
                if (!this.$v.form.slug.$dirty) return errors
                !this.$v.form.slug.required && errors.push('Slug is required.')
                return errors
            },
        },
        methods: {
            ...mapMutations('article', ['CLEAR_FORM']),
            submit () {
                this.$v.$touch()
                if (!this.$v.$invalid) {
                    console.log('valid');
                }
            },
            clear () {
                this.$v.$reset()
                this.CLEAR_FORM()
            },
        },
        destroyed() {
            this.CLEAR_FORM()
        }
    }
</script>

<style>
    .ql-editor {
        height: 40vh;
    }
</style>

And this is validation from Laravel that I have.

namespace App\Http\Requests\API\Admin\Article;

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
use App\Http\Requests\API\ApiRequest;

class StoreArticleRequest extends ApiRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'title' => 'required',
            'content' => 'required',
            'image' => 'required|mimes:jpg,jpeg,png,bmp|max:512',
            'category' => 'required',
            'slug' => 'required|unique:articles'
        ];
    }

    /**
     * Throw Http Response Exception
     *
     * @param Validator $validator
     * @return void
     */
    protected function failedValidation(Validator $validator)
    {
        throw new HttpResponseException($this->validatorResponse('failed', 422, $validator->errors()));
    }
}

Maybe all of you can share your experiences and solutions regarding this problem.

What is the best way to do it?

Do I not need to use Vuelidate and only use error responses from my Backend?

1 Answer 1

1

The general best practice is to validate on both client and backend, but definitely on the backend. Your service needs to protect against malformed data being submitted and persisted.

As for the client side, validation is nice to provide immediate feedback and prevent bad requests to your server, which will just take more time and pollute your logs with preventable 400 errors. Ideally one framework would serve as the validation on both sides, and some do. Not sure about your combination. I chose to use Vee-Validate with Vuetify on client and FluentValidation in .NET core backend, but the rules are duplicated.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the solution you provided. Maybe I would be better off using both if that's the best way to do it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.