DatePicker.vue 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <!--
  2. Sélecteur de dates avec Vuetify
  3. @see https://vuetifyjs.com/en/components/date-pickers/
  4. -->
  5. <template>
  6. <v-layout row wrap>
  7. <v-menu
  8. v-model="menu"
  9. :close-on-content-click="false"
  10. :nudge-right="40"
  11. lazy
  12. transition="scale-transition"
  13. offset-y
  14. :max-width="290"
  15. :min-width="290"
  16. :position-x="positionX"
  17. :position-y="positionY"
  18. >
  19. <template #activator="{ props: attrs }">
  20. <v-text-field
  21. v-model="displayDate"
  22. :label="label"
  23. :readonly="true"
  24. v-bind="attrs"
  25. />
  26. </template>
  27. <v-date-picker
  28. :model-value="modelValue"
  29. :locale="i18n.locale.value"
  30. no-title
  31. scrollable
  32. @update:model-value="updateDate"
  33. />
  34. </v-menu>
  35. </v-layout>
  36. </template>
  37. <script setup lang="ts">
  38. import { ref, computed, nextTick, watch, type PropType } from 'vue'
  39. import { useI18n } from 'vue-i18n'
  40. const props = defineProps({
  41. modelValue: Date,
  42. label: {
  43. type: String,
  44. default: '',
  45. },
  46. format: {
  47. type: String,
  48. default: null,
  49. },
  50. /**
  51. * Position du date-picker
  52. * @see https://vuetifyjs.com/en/api/v-menu/#props-position
  53. */
  54. position: {
  55. type: String as PropType<'left' | 'center' | 'right'>,
  56. default: 'center',
  57. },
  58. })
  59. const emit = defineEmits(['update:modelValue'])
  60. const i18n = useI18n()
  61. const menu = ref(false)
  62. const positionX = ref(0)
  63. const positionY = ref(0)
  64. const displayDate = computed({
  65. get: () => {
  66. if (!props.modelValue) return ''
  67. if (props.format) {
  68. return new Intl.DateTimeFormat(i18n.locale.value, {
  69. year: 'numeric',
  70. month: '2-digit',
  71. day: '2-digit',
  72. hour: props.withTime ? '2-digit' : undefined,
  73. minute: props.withTime ? '2-digit' : undefined,
  74. }).format(props.modelValue)
  75. }
  76. return props.modelValue.toLocaleDateString(i18n.locale.value)
  77. },
  78. set: () => {},
  79. })
  80. function updateDate(value: Date) {
  81. emit('update:modelValue', value)
  82. menu.value = false
  83. }
  84. function updatePosition() {
  85. nextTick(() => {
  86. const activator = document.querySelector('.v-menu__activator')
  87. if (activator) {
  88. const rect = activator.getBoundingClientRect()
  89. positionX.value = rect.left
  90. positionY.value = rect.bottom
  91. }
  92. })
  93. }
  94. watch(menu, (val) => {
  95. if (val) updatePosition()
  96. })
  97. </script>
  98. <style scoped>
  99. .v-menu__content {
  100. position: absolute !important;
  101. }
  102. </style>