Text.vue 3.3 KB

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