Why `@change` trigger don't work for v-data-picker?

Viewed 6563

I use v-calendar package in my Vue.js application.

I want to send selected data range values to parent component. Why @change trigger don't work?

Parent.vue:

<template>
    <div>
        <Child @setRange="setRange" :range="range"/>
    </div>
</template>

<script>
data() {
    return {
        range: this.range,
    }
},
mounted() {
    firstCallToPage();
},
methods: {
    firstCallToPage(){
        axios.get('URL').then(response => {
            let self = this;
            this.range = {
                start: response.startDate,
                end: response.endDate,
            };
        }
    },
    setRange(range_value) {
        this.range = range_value;
    }
}
</script>

Child.vue:

<v-date-picker class='v-date-picker'
                       mode='range'
                       v-model='rangeValue'
                       :show-day-popover=false
                       :max-date='new Date()'
                       show-caps
                       :input-props='{placeholder: "", readonly: true}'
                       @change="sendRange">
</v-date-picker>
props: {
    range: {
        type: Object,
    },
},

data() {
  return {
    rangeValue: this.range
  }
},

sendRange: function () {
    this.$emit('setRange', this.rangeValue);
}

ERROR in console:

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: "range"
3 Answers

The error message is pretty explicit. The problem is that you give a prop to your child component (the one that contains v-date-picker) and you are overriding this prop with v-model (v-model is just syntactic sugar for :value and @change).

Derive your prop's value with a data value and use it for your operations:

<v-date-picker class='v-date-picker'
                       mode='range'
                       v-model='rangeValue'
                       :show-day-popover=false
                       :max-date='new Date()'
                       show-caps
                       :input-props='{placeholder: "", readonly: true}'
                       >
</v-date-picker>
props: {
    range: {
        type: Object,
    },
},

data() {
  return {
    rangeValue: this.range
  }
},

sendRange: function () {
    this.$emit('setRange', this.rangeValue);
}

Try @input instead of @change. In v-datetime-picker works only with @input.

Instead of using a method, you can make use of watch...

Consider you have the following attributes in the range Object

range: {
   start:value,
   end: value
}

<v-date-picker class='v-date-picker'
                       mode='range'
                       v-model='rangeValue'
                       :show-day-popover=false
                       :max-date='new Date()'
                       show-caps
                       :input-props='{placeholder: "", readonly: true}'
                       >
</v-date-picker>
props: {
    range: {
        type: Object,
    },
},
watch: {
  'rangeValue.start': function(newVal){
      this.$emit('setRange', newVal);
  }
},
data() {
  return {
    rangeValue: this.range
  }
}

Related