AppTextArea.vue 1.2KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. <script setup>
  2. import { computed } from 'vue'
  3. const props = defineProps({
  4. label: {
  5. type: String,
  6. required: true,
  7. },
  8. disabled: {
  9. type: Boolean,
  10. default: false,
  11. },
  12. placeholder: {
  13. type: String,
  14. required: true,
  15. },
  16. error: {
  17. type: String,
  18. default: null,
  19. },
  20. rows: {
  21. type: Number,
  22. default: 5,
  23. },
  24. cols: {
  25. type: Number,
  26. default: 30,
  27. },
  28. modelValue: null,
  29. })
  30. const isError = computed(() => (props.error ? true : false))
  31. const forLabel = computed(() => props.label.toLowerCase().replace(/\s+/g, '-'))
  32. const ariaDescribedbyLabel = computed(
  33. () => props.label.toLowerCase().replace(/\s+/g, '-') + '-error'
  34. )
  35. </script>
  36. <template>
  37. <div class="field">
  38. <label :for="forLabel">{{ label }}</label>
  39. <Textarea
  40. class="w-full"
  41. :class="{ 'p-invalid': isError }"
  42. :id="forLabel"
  43. :model-value="modelValue"
  44. :placeholder="placeholder"
  45. :disabled="disabled"
  46. :auto-resize="true"
  47. :rows="rows"
  48. :cols="cols"
  49. @input="$emit('update:modelValue', $event.target.value)"
  50. />
  51. <small
  52. v-if="error"
  53. :id="ariaDescribedbyLabel"
  54. :class="{ 'p-error': isError }"
  55. >
  56. {{ error }}
  57. </small>
  58. </div>
  59. </template>