<template> <q-input v-model="dateTime" filled :readonly="readonly" :label="label" :placeholder="placeholder" :rules="customRules" :clearable="clearable" v-bind="attrs" @clear="dateTime = ''" > <template #append> <q-icon v-if="'date' || type == 'datetime'" name="mdi-calendar" class="cursor-pointer"> <q-popup-proxy ref="qDateProxy" transition-show="scale" transition-hide="scale"> <q-date v-model="date" mask="YYYY-MM-DD"> <div class="row items-center justify-end"> <q-btn v-close-popup label="Schließen" color="primary" flat /> </div> </q-date> </q-popup-proxy> </q-icon> <q-icon v-if="type == 'time' || type == 'datetime'" name="mdi-clock-outline" class="cursor-pointer" > <q-popup-proxy ref="qTimeProxy" transition-show="scale" transition-hide="scale"> <q-time v-model="time" mask="HH:mm"> <div class="row items-center justify-end"> <q-btn v-close-popup label="Schließen" color="primary" flat /> </div> </q-time> </q-popup-proxy> </q-icon> </template> </q-input> </template> <script lang="ts"> import { computed, defineComponent, PropType } from 'vue'; import { date as q_date } from 'quasar'; import { stringIsDate, stringIsTime, stringIsDateTime, Validator } from 'src/utils/validators'; export default defineComponent({ name: 'IsoDateInput', props: { modelValue: { type: Object as PropType<Date | undefined>, default: undefined }, type: { type: String, default: 'date', validator: (value: string) => ['date', 'time', 'datetime'].indexOf(value) !== -1, }, label: { type: String, default: 'Datum' }, readonly: Boolean, rules: { type: Array as PropType<Validator[]>, default: () => [], }, }, emits: { 'update:modelValue': (date?: Date) => !!date || !date }, setup(props, { emit, attrs }) { const customRules = computed(() => [ props.type == 'date' ? stringIsDate : props.type == 'time' ? stringIsTime : stringIsDateTime, ...props.rules, ]); const clearable = computed(() => customRules.value.every((r) => (<Validator>r)(undefined) === true) ); const placeholder = computed(() => { switch (props.type) { case 'date': return 'YYYY-MM-DD'; case 'time': return 'HH:mm'; case 'datetime': return 'YYYY-MM-DD HH:mm'; } throw 'Invalid type given'; }); const date = computed({ get: () => q_date.formatDate(props.modelValue, 'YYYY-MM-DD'), set: (v: string) => { const d = modifyDate(v); if (d) emit('update:modelValue', d); }, }); const time = computed({ get: () => q_date.formatDate(props.modelValue, 'HH:mm'), set: (v: string) => { const d = modifyTime(v); if (d) emit('update:modelValue', d); }, }); const dateTime = computed({ get: () => (props.modelValue ? q_date.formatDate(props.modelValue, placeholder.value) : ''), set: (v: string) => { if (!v) emit('update:modelValue', undefined); switch (props.type) { case 'date': date.value = v; break; case 'time': time.value = v; break; case 'datetime': const split = v.split(' ').filter((c) => c !== ''); if (split.length == 2) { const d = modifyTime(split[1], modifyDate(split[0])); if (d) emit('update:modelValue', d); } break; } }, }); function modifyTime(v: string, d: Date | undefined = props.modelValue) { if (d && /^\d\d:\d\d$/.test(v)) { const split = v.split(':'); return q_date.adjustDate(d, { hours: +split[0], minutes: +split[1] }); } } function modifyDate(v: string, d: Date | undefined = props.modelValue) { if (!d) d = new Date(); if (/^\d{4}-\d\d-\d\d$/.test(v)) { const split = v.split('-'); return q_date.adjustDate(d, { year: +split[0], month: +split[1], date: +split[2], }); } } return { attrs, clearable, customRules, date, dateTime, placeholder, time, }; }, }); </script>