AppTextArea.vue 1.3KB

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