Reputation: 197
I'm using Vuetify framework for Vue on my current project and I've created a custom component based on the v-date-picker which i plan on using in multiple places. below is the code ;
Child component (custom v-date-picker)
<template>
<v-dialog
ref="dialog"
v-model="modal"
:return-value.sync="date"
persistent
width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="date"
:label=title
prepend-icon="event"
readonly
v-on="on"
></v-text-field>
</template>
<v-date-picker v-model="date" scrollable>
<v-spacer></v-spacer>
<v-btn text color="primary" @click="modal = false">Cancel</v-btn>
<v-btn text color="primary" @click="$refs.dialog.save(date)">OK</v-btn>
</v-date-picker>
</v-dialog>
</template>
<script>
export default {
props:[
'title','date'
],
data () {
return {
modal:false,
}
},
}
</script>
Parent Component (Which is a dialog)
<template>
<v-dialog
width="800px"
v-model="dialog"
>
<v-card>
<!-- <v-card-title class="grey darken-2">
Create contact
</v-card-title> -->
<v-container>
<v-row class="mx-2">
<v-col cols="3">
<date-picker-component :date="beginDate" title="Begin Date"></date-picker-component>
</v-col>
<v-col cols="3">
<date-picker-component :date="endDate" title="End Date"></date-picker-component>
</v-col>
</v-row>
</v-container>
<v-card-actions>
<v-spacer />
<v-btn
text
color="primary"
@click="dialog = false"
>Cancel</v-btn>
<v-btn
text
@click="createEvent"
>Create Event</v-btn>
</v-card-actions>
</v-card>
<v-overlay :value="overlay">
<v-progress-circular indeterminate size="64"></v-progress-circular>
</v-overlay>
<v-dialog
v-model="resultDialog"
max-width="290"
>
<v-card>
<v-card-title class="headline"><v-icon class="pr-2" color="green" st>mdi-check-circle</v-icon> Event Manager</v-card-title>
<v-card-text>
{{resultDialogMessage}}
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="green darken-1"
text
@click="resultDialog = false"
>
OK
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-dialog>
</template>
<script>
import Vue from 'vue';
import DatePicker from "../../widgets/DatePicker";
export default {
name: 'CreateEvent',
props:['dialog'],
components:{
'date-picker-component':DatePicker,
},
data () {
return {
resultDialog:false,
resultDialogMessage:"",
overlay:false,
beginDate:new Date().toISOString().substr(0, 10),
endDate:new Date().toISOString().substr(0, 10),
}
},
};
</script>
The v-date-picker works fine, but immediately i pick a date, i get the following error in the console;
[Vue warn]: 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: "date
As a result, I am unable to get the chosen date from the child component and the date just reverts back to the initial date.
Is there something I've left out, what am I doing wrong ?
Upvotes: 1
Views: 4184
Reputation: 6544
In vue data to a child, component should be passed as a prop and to the parent component, it should be passed by emitting back. If you use the same variable for passing and emitting value back vue warns you. You need to change your date-picker-component as follows so that prop is not directly getting changed by the child. Instead use a local data.
<template>
<v-dialog
ref="dialog"
v-model="modal"
:return-value.sync="localDate" //Changed here
persistent
width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="localDate" //Changed here
:label=title
prepend-icon="event"
readonly
v-on="on"
></v-text-field>
</template>
<v-date-picker v-model="localDate" scrollable> //Changed here
<v-spacer></v-spacer>
<v-btn text color="primary" @click="modal = false">Cancel</v-btn>
<v-btn text color="primary" @click="$refs.dialog.save(localDate)">OK</v-btn> //Changed here
</v-date-picker>
</v-dialog>
</template>
<script>
export default {
props:[
'title','date'
],
data () {
return {
modal:false,,
localDate: this.date
}
},
watch: {
localDate(){
this.$emit('update', this.localDate)
}
}
}
</script>
Now in your parent component, you use as follows
<date-picker-component
:date="endDate"
@update="(v) => (endDate = v)"
title="End Date">
</date-picker-component>
Upvotes: 2