I´m trying to do that my v-date-picker allow that my users can write date with keyboard and select date with date-picker. I´m reading documentation, i´m showing examples... but i can´t find solution. I think that should be very simple but i don´t know how i can to do this. I hope that anybody can help me.
I have this component, FormDatePicker.vue
that all content it´s:
<template>
<v-flex>
<strong>{{ label }}</strong>
<v-menu
ref="dateMenu"
v-model="dateMenu"
:close-on-content-click="false"
:nudge-right="40"
transition="scale-transition"
offset-y
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
slot="activator"
v-model="valorDateFormatted"
persistent-hint
append-outer-icon="event"
clearable
solo
v-on="on"
:error-messages="errorMessages"
@click:clear="limpiarDate()"
></v-text-field>
</template>
<v-date-picker
locale="es-ES"
v-on="$listeners"
v-model="currentValue"
no-title
first-day-of-week=1
@input="dateChanged()"
:min="min"
:max="max"
:disabled="desactivar"
@change="useSelectedData"
></v-date-picker>
</v-menu>
</v-flex>
</template>
<script>
export default {
inheritAttrs: false,
data: () => ({
dateMenu: false,
}),
props: {
errorMessages: { type: Array, default: null},
label: { type: String, default: ''},
value: { default: ''}, //Nota: Elimino el type: String porque provoca un error cuando le paso números.
min: { type: String, default: null },
max: { type: String, default: null },
desactivar: { type: Boolean, default: null}
},
computed: {
inputListeners: function () {
var vm = this
// `Object.assign` merges objects together to form a new object
return Object.assign({},
// We add all the listeners from the parent
this.$listeners,
// Then we can add custom listeners or override the
// behavior of some listeners.
{
// This ensures that the component works with v-model
input: function (event) {
vm.$emit('input', event.target.value)
}
}
)
},
valorDateFormatted: {
get : function () {
return this.formatDate(this.value);
},
set: function(value) {
return this.formatDate(value);
}
},
currentValue: {
get: function() {
if (this.value != null) {
return this.value.split(' ')[0];
}
return this.value;
},
set: function(val) {
this.$emit('input', val);
}
}
},
methods: {
dateChanged() {
this.dateMenu = false;
},
formatDate (date) {
if (!date) return null
const [year, month, day] = date.split(' ')[0].split('-')
return `${day}/${month}/${year}`
},
limpiarDate(){
this.$emit('input', null);
},
}
}
</script>
<style scoped>
.theme--light.v-input >>> input, .theme--light.v-input >>> textarea{
margin-top: 10px;
}
</style>
I tryed add @blur and function tu blur, i tryed add @focus and function to focus, but not run.
Thank your very much for read me and sorry for my bad english
I read Shkirkov's answer and I think it can be done simpler.
What we want is to bind 2 values in the v-text-field v-model: the date value by the date picker and the one written with the keyboard. For that, we have to define the getter and setter in the computed variable and we CAN NOT put "readonly" as an attribute for v-date-picker.
Your template will look like this:
<template>
<v-menu
v-model="menu"
:close-on-content-click="false"
transition="scale-transition"
offset-y
max-width="290px"
min-width="290px"
>
<template #activator="{ on, attrs }">
<v-text-field
v-model="formattedDate"
v-bind="attrs"
v-on="on"
ref="datePicker"
/>
</template>
<v-date-picker
color="secondary"
locale="ru-RU"
no-title
v-model="internalDate"
@input="onDatePickerValueChanged"
:first-day-of-week="1"
:max="max"
/>
</v-menu>
</template>
And as for your script:
<script>
export default {
name: 'x-date-picker',
data() {
return {
menu: false,
internalDate: null¿
}
},
computed: {
/**
* v-date-picker uses format YYYY-MM-DD, but out local format is DD.MM.YYYY
*/
formattedDate: {
get() {
return (this.internalDateValue && this.internalDateValue.length === 10)
? this.$moment(this.internalDate).format('DD.MM.YYYY')
: this.internalDateValue
},
set(newValue) {
if(newValue && newValue.length==10){
let newDate = `${newValue.substring(6, 10)}-${newValue.substring(3, 5)}-${newValue.substring(0, 2)}`
this.internalDate = newDate
}
}
We need to pass to internalDate the date in the format YYYY-MM-DD because is the date picker's format!
Hope it works for you :)