I want to proxy <vue-date-picker/>
, which exposes a Date-based v-model in a way that it can be used with Dayjs (which we use across the app) instead. How can I achieve this? I am on latest Vue with composition API.
I know I need to use @update:model-value and :model-value to split the 2-way data binding into 2x1-way and have a conversion in between, but I don't know how to pass a v-model value into a ref() and at the same time emit events which can be consumed as a v-model in a parent component. I tried out many variations, my current code looks like this:
const convertedValue = ref(dayjs(props.value).toDate());
watchEffect(() => {
convertedValue.value = dayjs(props.value).toDate();
});
watchEffect(() => {
emit('update:value', dayjs(convertedValue.value));
});
...
<vue-date-picker :model-value="convertedValue" />
But it just does not work. This should be a pretty common use-case, no? What can I do?
EDIT: thanks to the answer from Alexander and a colleague of mine, I managed to get it working like this:
const value = computed(() => convertToDatePicker(props.modelValue));
const emit = defineEmits<{
'update:model-value': [date: dayjs.Dayjs | null];
}>();
function handleEmit(event: ModelValue) {
emit('update:model-value', convertToDayjs(event));
}
...
:model-value="value"
@update:model-value="handleEmit"
There is a standard way to use computed()
:
// use it as v-model for the input in the template
const value = computed({
get(){
return dayjs(props.value).toDate();
},
set(val){
emit('update:value', dayjs(val));
}
});
I also suggest to use modelValue
instead of value
as the prop so you can bind your proxy component with clean v-model
too.
In the Vue 3.3 a macro defineModel()
is available which accepts the same get/set as the second parameter.
It is marked as experimental, stable in 3.4