4
votes

Error:

[Vue warn]: Property or method "$v" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

found in

---> at resources\assets\js\components\products\Product_create.vue

I'm using Vue.js and Vuelidate as validator, I've copied and pasted this code from here https://jsfiddle.net/Frizi/b5v4faqf/ but it still doesn't work :

Vue Component :

    <template >
      <input v-model="$v.text.$model" :class="status($v.text)">
      <!-- <pre>{{ $v }}</pre> -->
    </template>
    
    <script>
    import { required, minLength, between } from 'vuelidate/lib/validators'
      export default {
         data() {
           return {
        text: ''
            }
           },
           validations: {
            text: {
            required,
            minLength: minLength(5)
          }
        },
        methods: {
            status(validation) {
            return {
                error: validation.$error,
              dirty: validation.$dirty
            }
          }
        }
      }
    </script>

App.js

    require('./bootstrap');
    
    window.Vue = require('vue');
    window.VueRouter = require('vue-router').default;
    window.VueAxios = require('vue-axios').default;
    window.Axios = require('axios').default;
    window.VueFormWizard = require('vue-form-wizard');
    window.Vuelidate = require('vuelidate').default;
    import 'vue-form-wizard/dist/vue-form-wizard.min.css';

    Vue.use(VueRouter,VueAxios,axios,VueFormWizard,Vuelidate);

    const ProductOptionCreate = Vue.component('po-create',require('./components/products/ProductOption_create.vue'));
    const ProgressModal = Vue.component('vue-modal',require('./components/ProgressModal.vue'));
    const ProductIndex = Vue.component('product-list',require('./components/products/Product_index.vue'));
    const productshow = Vue.component('productshow',require('./components/products/ProductOption_show.vue'));
    const ProductCreate = Vue.component('product-create',require('./components/products/Product_create.vue'));
    

    const app = new Vue({
      el:'#app',
    
    });

What's wrong with this code?

5
You are not defining $v, you should define it under App.jsRodrigo Mata
@RodrigoMata can u tell me how it's work?Faris Dewantoro
As far as I can tell, Vue.use() takes only one argument. You are attempting to pass it five.Phil
Sorry, Vue.use() takes one or two arguments, the first being the required plugin and the second being an optional configuration objectPhil
ohh oke thanks a lot broo, how about if i have five? what should i do? @PhilFaris Dewantoro

5 Answers

6
votes

The problem is that $v is not defined at a component level, and it is because of the order of your components, you need to reorder them like so:

// ... other stuff
import 'vue-form-wizard/dist/vue-form-wizard.min.css';

Vue.use(Vuelidate);

const ProductOptionCreate = // ... rest of your components
2
votes

I think the problem was that the validation was declared within the data property of the component and not as a direct property of the component.

So

export default {
     validations: {
        text: {
        required,
        minLength: minLength(5)
      },
     data() {
       return {
           text: ''
        }
       },
       
    },
    ........

instead of

export default {
     data() {
       return {
          text: ''
        }
       },
       validations: {
        text: {
        required,
        minLength: minLength(5)
      }
1
votes

The reason $v is not available on your instance is because you haven't instantiated the Vuelidate plugin. And that's because you tried to streamline the call to Vue.use().
Your current Vue.use() call only instantiates the first plugin (VueRouter) and passes VueAxios plugin object as VueRouter's config object. All subsequent arguments are ignored.

To streamline your calls to Vue.use(), you can't simply add more arguments to it.

Instead of this erroneous syntax (which breaks instantiation of all but first plugin):

Vue.use(VueRouter, VueAxios, axios, VueFormWizard, Vuelidate);

... you could use:

[[VueRouter], [VueAxios, axios], [VueFormWizard], [Vuelidate]]
  .forEach(args => Vue.use(...args));

With Typescript: unfortunately, TS parser wrongly includes 0 arguments as a possible outcome of the spread operator in the above case, so you'd need to suppress it using:

[
  [VueRouter],
  [VueAxios, axios],
  [VueFormWizard],
  [Vuelidate]
  /* @ts-ignore: TS2557, TS wrong about array above having empty members */
].forEach(args => Vue.use(...args));

... at least for now ("typescript": "^3.9.7").

The above syntax is the exact equivalent of:

Vue.use(VueRouter);
Vue.use(VueAxios, axios);
Vue.use(VueFormWizard);
Vue.use(Vuelidate); // <= this is what you were missing, basically
                    // but your syntax also broke VueAxios and VueFormWizard install

On a personal note: although a tad more repetitive, I actually find the Vue.use() syntax cleaner in this case (more readable).

1
votes

The validations should be defined in a component in order to initialize this.$v

I had a typo and didn't realized I was declaring validations inside methods.

methods: {

   validations: {
      isUScitizen: { required },
   },
}

And I was trying to access this.$v which was undefined because the component didn't had validations defined.

-9
votes

You must specify this.$v and there will be no error