Text.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <!--
  2. Champs de saisie de texte, à placer dans un composant `UiForm`
  3. @see https://vuetifyjs.com/en/components/text-fields/
  4. -->
  5. <template>
  6. <v-text-field
  7. :model-value="modelValue"
  8. :label="(label || field) ? $t(label ?? field) : undefined"
  9. :rules="rules"
  10. :disabled="readonly"
  11. :type="(type === 'password' && show) ? 'text' : type"
  12. :error="error || !!fieldViolations"
  13. :error-messages="errorMessage || (fieldViolations ? $t(fieldViolations) : '')"
  14. :append-icon="type === 'password' ? (show ? 'mdi-eye' : 'mdi-eye-off') : ''"
  15. :variant="variant"
  16. @click:append="show = !show"
  17. @update:model-value="onUpdate($event)"
  18. @change="onChange($event)"
  19. />
  20. <!-- v-cleave="mask"-->
  21. </template>
  22. <script setup lang="ts">
  23. import {ref} from "@vue/reactivity";
  24. import {useFieldViolation} from "~/composables/form/useFieldViolation";
  25. import {useNuxtApp} from "#app";
  26. import {useI18n} from "vue-i18n";
  27. import {mask} from "vue-the-mask";
  28. const props = defineProps({
  29. /**
  30. * v-model
  31. */
  32. modelValue: {
  33. type: [String, Number],
  34. required: false,
  35. default: null
  36. },
  37. /**
  38. * Nom de la propriété d'une entité lorsque l'input concerne cette propriété
  39. * - Utilisé par la validation
  40. * - Laisser null si le champ ne s'applique pas à une entité
  41. */
  42. field: {
  43. type: String,
  44. required: false,
  45. default: null
  46. },
  47. /**
  48. * Label du champ
  49. * Si non défini, c'est le nom de propriété qui est utilisé
  50. */
  51. label: {
  52. type: String,
  53. required: false,
  54. default: null
  55. },
  56. /**
  57. * Type d'input HTML
  58. * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/button
  59. */
  60. type: {
  61. type: String,
  62. required: false,
  63. default: null
  64. },
  65. /**
  66. * Définit si le champ est en lecture seule
  67. */
  68. readonly: {
  69. type: Boolean,
  70. required: false,
  71. default: false
  72. },
  73. /**
  74. * Règles de validation
  75. * @see https://vuetify.cn/en/components/forms/#validation-with-submit-clear
  76. */
  77. rules: {
  78. type: Array,
  79. required: false,
  80. default: () => []
  81. },
  82. /**
  83. * Le champ est-il actuellement en état d'erreur
  84. */
  85. error: {
  86. type: Boolean,
  87. required: false,
  88. default: false
  89. },
  90. /**
  91. * Si le champ est en état d'erreur, quel est le message d'erreur?
  92. */
  93. errorMessage: {
  94. type: String,
  95. required: false,
  96. default: null
  97. },
  98. /**
  99. * Masque de saisie
  100. * @see https://github.com/nosir/cleave.js/
  101. */
  102. mask: {
  103. type: [Array, Boolean],
  104. required: false,
  105. default: false
  106. },
  107. /**
  108. * @see https://vuetifyjs.com/en/api/v-autocomplete/#props-variant
  109. */
  110. variant: {
  111. type: String,
  112. required: false,
  113. default: 'filled'
  114. }
  115. })
  116. const { app } = useNuxtApp()
  117. const i18n = useI18n()
  118. const { fieldViolations, updateViolationState } = useFieldViolation(props.field)
  119. const show = ref(false)
  120. const emit = defineEmits(['update:model-value', 'change'])
  121. const onUpdate = (event: string) => {
  122. emit('update:model-value', event)
  123. }
  124. const onChange = (event: Event | undefined) => {
  125. updateViolationState(event)
  126. emit('change', event)
  127. }
  128. // const label = computed(() => {
  129. // if (props.label)
  130. // })
  131. </script>
  132. <style scoped lang="scss">
  133. input:read-only{
  134. color: rgb(var(--v-theme-neutral));
  135. }
  136. </style>