title: Laravel, Vue Js with Vuetify and Vuelidate
body: <p>I want to ask about validation in <strong>Laravel</strong> and <strong>Vue JS.</strong></p>
  <p>Here I use <strong>Vue JS</strong> separately from <strong>Laravel</strong>. Then I was confused to use <strong>validation</strong> from <strong>Backend</strong> and <strong>Frontend</strong> or better than just one of them.</p>
  <p>In this case at <strong>Vue JS</strong> I use <strong>Vuetify</strong>, <strong>Vuelidate</strong> and <strong>Vuex</strong>.</p>
  <p>I have tried <strong>validation</strong> on <strong>Vuetify</strong> using <strong>Vuelidate</strong>, this is very simple.</p>
  <p>But I am confused to choose, Am I just enough to make <strong>validation</strong> in Vue only? or still Retrieve all error responses that are only sent from <strong>Backend</strong>.</p>
  <p>What makes me confused if I only use <strong>validation</strong> in <strong>Frontend</strong> is not everything I can make. For example <strong>validation</strong> of image <strong>types</strong>, image <strong>sizes</strong>, <strong>unique</strong> data and others.</p>
  <p>What I'm afraid of is just <strong>validating</strong> on <strong>Frontend</strong>. I have to <strong>rebuild</strong> and this is very inefficient in my opinion.</p>
  <p>This is an example of <strong>validation</strong> in <strong>Vue JS</strong> that I have.</p>
  <pre class="lang-html prettyprint-override"><code>&lt;template&gt;
      &lt;v-container
          fluid
          tag=&quot;section&quot;
      &gt;
      &lt;v-row
          align=&quot;center&quot;
          justify=&quot;center&quot;
      &gt;
          &lt;v-col
              cols=&quot;12&quot;
          &gt;
              &lt;form&gt;
                  &lt;v-text-field
                      class=&quot;mb-5&quot;
                      v-model=&quot;form.title&quot;
                      :error-messages=&quot;errors.title&quot;
                      :counter=&quot;10&quot;
                      label=&quot;Title&quot;
                      required
                      dense
                      @input=&quot;$v.form.title.$touch()&quot;
                      @blur=&quot;$v.form.title.$touch()&quot;
                  &gt;&lt;/v-text-field&gt;
                  &lt;quill-editor
                      class=&quot;mb-5&quot;
                      v-model=&quot;form.content&quot;
                      :options=&quot;editorOption&quot;
                  &gt;&lt;/quill-editor&gt;
                  &lt;p class=&quot;display-6&quot; v-if=&quot;errors.content&quot;&gt;{{ errors.content }}&lt;/p&gt;
                  &lt;v-file-input
                      class=&quot;mb-5&quot;
                      :error-messages=&quot;errors.image&quot;
                      v-model=&quot;form.image&quot;
                      label=&quot;File input&quot;
                      chips
                      dense
                      clear-icon
                      @validate-on-blur=&quot;$v.form.image.$touch()&quot;
                  &gt;
                  &lt;/v-file-input&gt;
  
                  &lt;v-select
                      class=&quot;mb-5&quot;
                      :items=&quot;items&quot;
                      label=&quot;Category&quot;
                      dense
                      chips
                      counter
                  &gt;&lt;/v-select&gt;
  
                  &lt;v-text-field
                      class=&quot;mb-5&quot;
                      v-model=&quot;form.slug&quot;
                      :counter=&quot;10&quot;
                      label=&quot;Slug&quot;
                      required
                      dense
                      :error-messages=&quot;errors.slug&quot;
                      @input=&quot;$v.form.slug.$touch()&quot;
                      @blur=&quot;$v.form.slug.$touch()&quot;
                  &gt;&lt;/v-text-field&gt;
                  &lt;v-btn class=&quot;mr-4&quot; @click=&quot;submit&quot;&gt;submit&lt;/v-btn&gt;
                  &lt;v-btn @click=&quot;clear&quot;&gt;clear&lt;/v-btn&gt;
              &lt;/form&gt;
          &lt;/v-col&gt;
      &lt;/v-row&gt;
      &lt;/v-container&gt;
  &lt;/template&gt;
  
  &lt;script&gt;
      // * 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 =&gt; state.form
              }),
              titleErrors () {
                  if (!this.$v.form.title.$dirty) return errors
                  !this.$v.form.title.required &amp;&amp; errors.push('Title is required.')
                  return errors
              },
              slugErrors () {
                  if (!this.$v.form.slug.$dirty) return errors
                  !this.$v.form.slug.required &amp;&amp; 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()
          }
      }
  &lt;/script&gt;
  
  &lt;style&gt;
      .ql-editor {
          height: 40vh;
      }
  &lt;/style&gt;
  </code></pre>
  <p>And this is <strong>validation</strong> from <strong>Laravel</strong> that I have.</p>
  <pre class="lang-php prettyprint-override"><code>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' =&gt; 'required',
              'content' =&gt; 'required',
              'image' =&gt; 'required|mimes:jpg,jpeg,png,bmp|max:512',
              'category' =&gt; 'required',
              'slug' =&gt; 'required|unique:articles'
          ];
      }
  
      /**
       * Throw Http Response Exception
       *
       * @param Validator $validator
       * @return void
       */
      protected function failedValidation(Validator $validator)
      {
          throw new HttpResponseException($this-&gt;validatorResponse('failed', 422, $validator-&gt;errors()));
      }
  }
  
  </code></pre>
  <p>Maybe all of you can share your experiences and solutions regarding this problem.</p>
  <p>What is the best way to do it?</p>
  <p>Do I not need to use <strong>Vuelidate</strong> and only use error responses from my <strong>Backend</strong>?</p>