DefaultInput.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <template>
  2. <div class="default-input column" :class="attrs.class" :style="attrs.style">
  3. <div class="default-input-col col">
  4. <q-input
  5. ref="inputRef"
  6. v-model="model"
  7. class="default-input-field"
  8. color="secondary"
  9. hide-bottom-space
  10. label-color="secondary"
  11. lazy-rules="ondemand"
  12. v-bind="inputAttrs"
  13. :bg-color
  14. :class="[inputClass, { 'required-field': required }]"
  15. :error="!!error"
  16. :error-message="normalizedErrorMessage"
  17. :input-class="nativeInputClass"
  18. :label
  19. :outlined
  20. :rules
  21. @update:model-value="error = null"
  22. >
  23. <template #append>
  24. <slot name="append">
  25. <q-icon v-if="icon" color="secondary" size="sm" :name="icon" />
  26. </slot>
  27. </template>
  28. </q-input>
  29. </div>
  30. </div>
  31. </template>
  32. <script setup>
  33. import { computed, useAttrs, useTemplateRef } from "vue";
  34. defineOptions({
  35. inheritAttrs: false,
  36. });
  37. const {
  38. bgColor,
  39. errorMessage,
  40. icon,
  41. inputClass,
  42. label,
  43. nativeInputClass,
  44. outlined,
  45. rules,
  46. } = defineProps({
  47. bgColor: {
  48. type: String,
  49. default: "white",
  50. },
  51. errorMessage: {
  52. type: String,
  53. default: undefined,
  54. },
  55. icon: {
  56. type: String,
  57. default: "",
  58. },
  59. inputClass: {
  60. type: String,
  61. default: null,
  62. },
  63. label: {
  64. type: String,
  65. default: "",
  66. },
  67. nativeInputClass: {
  68. type: String,
  69. default: null,
  70. },
  71. outlined: {
  72. type: Boolean,
  73. default: false,
  74. },
  75. rules: {
  76. type: Array,
  77. default: () => [],
  78. },
  79. });
  80. const attrs = useAttrs();
  81. const inputRef = useTemplateRef("inputRef");
  82. const model = defineModel({ type: [String, Object, Array, Boolean, null] });
  83. const error = defineModel("error", {
  84. type: [String, Object, Array, Boolean, null],
  85. });
  86. const inputAttrs = computed(() => {
  87. // eslint-disable-next-line
  88. const { class: _, style: __, ...rest } = attrs;
  89. return rest;
  90. });
  91. const normalizedErrorMessage = computed(() => {
  92. if (errorMessage != null) {
  93. return errorMessage;
  94. }
  95. if (error.value == null) {
  96. return void 0;
  97. }
  98. if (typeof error.value === "boolean") {
  99. return void 0;
  100. }
  101. return String(error.value);
  102. });
  103. const required = computed(() => rules.some((rule) => rule?.$id === "required"));
  104. defineExpose({
  105. inputRef,
  106. });
  107. </script>
  108. <style scoped lang="scss">
  109. .default-input {
  110. min-width: 0;
  111. }
  112. .default-input[class*="col-"] {
  113. flex-grow: 0;
  114. flex-shrink: 0;
  115. }
  116. .default-input-field {
  117. min-width: 0;
  118. width: 100%;
  119. }
  120. :deep(.default-input-field .q-field__inner),
  121. :deep(.default-input-field .q-field__control),
  122. :deep(.default-input-field .q-field__control-container),
  123. :deep(.default-input-field .q-field__native),
  124. :deep(.default-input-field .q-field__input) {
  125. min-width: 0;
  126. max-width: 100%;
  127. }
  128. :deep(.default-input-field .q-field__native) {
  129. overflow: hidden;
  130. text-overflow: ellipsis;
  131. white-space: nowrap;
  132. }
  133. :deep(.q-field--outlined.q-field--rounded .q-field__control) {
  134. border-radius: 8px;
  135. }
  136. :deep(.required-field .q-field__label::after) {
  137. color: var(--q-negative);
  138. content: " *";
  139. }
  140. </style>