logaretm / vee-validate

✅ Painless Vue forms
https://vee-validate.logaretm.com/v4
MIT License
10.74k stars 1.26k forks source link

vuex model bound checkboxes not validated by validateAll in webpack #1316

Closed gerhard-h closed 6 years ago

gerhard-h commented 6 years ago

Versions

Describe the bug

I use the following markup (vuetify checkbox) to make my checkboxes required. If mycomputed would be part of data everything would work, but since I use vuex mycomputed is part of computed. The bug only happens when using webpack vue-cli 2.

<v-checkbox v-validate="'required'"
                      v-model="mycomputed"
                      :error-messages="errors.collect('mycomputed')
                      data-vv-name="mycomputed"
                      name="mycomputed"
                      type="checkbox"
                      label="Yes"
                      value="Y" />
<v-checkbox v-validate="'required'"
                      v-model="mycomputed"
                      :error-messages="errors.collect('mycomputed')
                      data-vv-name="mycomputed"
                      name="mycomputed"
                      type="checkbox"
                      label="No"
                      value="N" />

Bug 1: check Yes, uncheck Yes -> validation errors occur, check No - validation errors don't go away.

Bug 2: Reload page, nothing is checked, call validateAll -> validation succeeds (this happens because the Value="Y/N" is validated instead of the v-model)

HotFix

The following function is used inside vee-validate to check if the supplied v-model path is valid,

var hasPath = function (path, target) {
    var obj = target;
    return path.split('.').every(function (prop) {
        if (!Object.prototype.hasOwnProperty.call(obj, prop)) {
            return false;
        }
        obj = obj[prop];
        return true;
    });
};

but .hasOwnProperty returns false for all computed properties.

when replacing the questionable line of code with

if (!(obj[prop] || obj[prop] === null || obj[prop] == 0 || obj[prop] == ""  )) {

everything works fine. Also this codereplacement worked:

if (!(prop in obj)) {

I don't know if this has any sideeffects?

To Reproduce (edited) Setting up an minimal project and replace two files

> vue init vuetifyjs/webpack vue-testcomputed
> cd vue-testcomputed
> npm install --save-dev vee-validate

App.vue

<template>
  <v-app>
    <form>
      <v-checkbox v-validate="'required'"
                  v-model="mycomputed"
                  :error-messages="errors.collect('mycomputed')"
                  value="Y"
                  label="Yes"
                  data-vv-name="mycomputed"
                  type="checkbox"
                  required></v-checkbox>
      <v-checkbox v-validate="'required'"
                  v-model="mycomputed"
                  :error-messages="errors.collect('mycomputed')"
                  value="N"
                  label="No"
                  data-vv-name="mycomputed"
                  type="checkbox"
                  required></v-checkbox>

         <v-checkbox v-validate="'required'"
                  v-model="mylocaldata"
                  :error-messages="errors.collect('mylocaldata')"
                  value="1"
                  label="I like working validation :)"
                  data-vv-name="mylocaldata"
                  type="checkbox"
                  required></v-checkbox>

      <v-btn @click="submit">submit</v-btn>
      <v-btn @click="clear">clear</v-btn>
    </form>
  </v-app>
</template>

<script>
export default {
  computed: {
    mycomputed: {get(){return this.mycomputeddata}, set(val){this.mycomputeddata = val}}
  },

  data: () => ({
    mycomputeddata: '',
    mylocaldata: ''  }),

  methods: {
    submit () {
      this.$validator.validateAll()
    },
    clear () {

      this.mycomputed = null
      this.$validator.reset()
    }
  },
  name: "App"
};
</script>
main.js
import Vue from 'vue'
import App from './App'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
import VeeValidate from 'vee-validate';

Vue.use(VeeValidate)
Vue.use(Vuetify)

new Vue({
  el: '#app',
  components: { App },
  template: '<App/>'
})

Expected behavior using computed properties in v-model should behave the same way as using data

Demo Link This demo shows, that the bug does not apear outside webpack https://codepen.io/lindwurm/pen/qYYMpa?editors=1010 Reasoning (as far as I understand ):in the codepen scenario template compilition will occur in the browser, while in the webpack scenario template compilation happens inside webpack. But data() is a function and will always be called in the browser, while computed: is an object (containing functions) and will be prepared by webpack and inherited down to the component in the browser.

logaretm commented 6 years ago

duplicate of #1310

logaretm commented 6 years ago

fixed by https://github.com/baianat/vee-validate/commit/1c28c012b048814e549bb6efc0262565cc3ea820