Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using v-model with a prop on VUE.JS

I'm trying to use a data coming from a prop with v-model, the following code works, but with a warning.

<template>
<div>
       <b-form-input v-model="value" @change="postPost()"></b-form-input>
</div>
</template>
<script>
    import axios from 'axios';
    export default {
        props: {
            value: String
        },
        methods: {
            postPost() {
                axios.put('/trajectory/inclination', {
                    body: this.value
                })
                    .then(response => {
                    })
                    .catch(e => {
                        this.errors.push(e)
                    })
            }
        }
    }
</script>

The warning says:

"Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "value"

So I changed and now I'm using a data as the warning says.

<template>
<div>
       <b-form-input v-model="_value" @change="postPost()"></b-form-input>
</div>
</template>
<script>
    import axios from 'axios';

    export default {
        props: {
            value: String
        },
        data() {
            return {
                _value: this.value
            }
        },
        methods: {
            postPost() {
                axios.put('/trajectory/inclination', {
                    body: this._value
                })
                    .then(response => {
                    })
                    .catch(e => {
                        this.errors.push(e)
                    })
            }
        }
    }

So now the code it's not working and the warning says:

"Property or method "_value" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option"

Any idea how to fix the first code to suppress the warning? (or some idea on how to fix the second code?)

Obs.: b-form-input it's not my componente, this is the Textual Input from Boostrap-Vue (Doc for b-form-input)

like image 330
user3142 Avatar asked Sep 11 '17 21:09

user3142


People also ask

Can you use V-model with Props?

In 2.2 we introduced the model component option that allows the component to customize the prop and event to use for v-model . However, this still only allowed a single v-model to be used on the component.

How do you handle Props in Vue?

To specify the type of prop you want to use in Vue, you will use an object instead of an array. You'll use the name of the property as the key of each property, and the type as the value. If the type of the data passed does not match the prop type, Vue sends an alert (in development mode) in the console with a warning.

Can I use Props in data Vue?

Using props in VueAfter you have set up the props, you can then use it inside your component as though the data was defined inside the same component. This means you can set up method calls and easily access this.

How do you pass an object as a prop in Vue?

To pass in the properties of an object as props, we can use the v-bind without the argument. Then the properties of post will be passed into blog-post as prop values. The property names are the prop names.


4 Answers

Answer is from https://github.com/vuejs/vue/issues/7434

Props are read-only, but you are trying to change its value with v-model. In this case, if you change the input value, the prop is not modified and the value is restored on the next update.

Use a data property or a computed setter instead:

computed: {   propModel: {     get () { return this.prop },     set (value) { this.$emit('update:prop', value) },   }, }, 

https://vuejs.org/v2/guide/computed.html#Computed-Setter

like image 141
nsv Avatar answered Sep 20 '22 14:09

nsv


Bert addresses your direct issue, but I think you should also know that your approach is a bit off. Since ultimately you are sending the new value to postPost, you don't really need to modify your local copy. Use the event object that is sent to the change handler to get the current value from the input.

Instead of v-model, just use :value, and don't include the invocation parentheses when specifying the change handler.

<template> <div>        <b-form-input :value="value" @change="postPost"></b-form-input> </div> </template> <script>     import axios from 'axios';     export default {         props: {             value: String         },         methods: {             postPost(event) {                 axios.put('/trajectory/inclination', {                     body: event.target.value                 })                     .then(response => {                     })                     .catch(e => {                         this.errors.push(e)                     })             }         }     } </script> 
like image 31
Roy J Avatar answered Sep 19 '22 14:09

Roy J


_ prefixed properties are reserved for Vue's internal properties.

Properties that start with _ or $ will not be proxied on the Vue instance because they may conflict with Vue’s internal properties and API methods.

Try changing _value to something that doesn't start with an underscore.

like image 35
Steve Holgado Avatar answered Sep 20 '22 14:09

Steve Holgado


One general workaround is to introduce a data-variable and watch the props to update-variable. This is quite subtle and so easy to get wrong so here's an example with a Vuetify modal using v-model (the same technique, in theory, should work with <input> and others):

<template>
  <v-dialog v-model="isVisible" max-width="500px" persistent>
  </v-dialog>
</template>

<script>
export default {
  name: 'Blablabla',
  props: {
    visible: { type: Boolean, required: true }
  },
  data() {
    isVisible: false
  },
  watch: {
    // `visible(value) => this.isVisible = value` could work too
    visible() {
      this.isVisible = this.$props.visible
    }
  }
}
</script>
like image 25
Abdullah Avatar answered Sep 18 '22 14:09

Abdullah