DefaultSelect.vue 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. <template>
  2. <div class="column" :class="attrs.class" :style="attrs.style">
  3. <div class="col">
  4. <q-select
  5. ref="selectRef"
  6. v-model="model"
  7. hide-bottom-space
  8. hide-dropdown-icon
  9. label-color="secondary"
  10. lazy-rules="ondemand"
  11. v-bind="selectAttrs"
  12. :bg-color
  13. :class="[inputClass, { 'required-field': required }]"
  14. :error="!!error"
  15. :error-message="errorMessage"
  16. :label
  17. :outlined
  18. :popup-content-class="popupContentClass"
  19. :rules
  20. @update:model-value="error = null"
  21. >
  22. <template v-for="(_, slotName) in $slots" #[slotName]="scope">
  23. <slot :name="slotName" v-bind="scope" />
  24. </template>
  25. <template #append>
  26. <q-icon :name="dropdownIcon" color="secondary" />
  27. </template>
  28. </q-select>
  29. </div>
  30. </div>
  31. </template>
  32. <script setup>
  33. import { computed, onBeforeMount, ref, useAttrs } from "vue";
  34. defineOptions({
  35. inheritAttrs: false,
  36. });
  37. const {
  38. bgColor,
  39. dropdownIcon,
  40. inputClass,
  41. label,
  42. outlined,
  43. popupContentClass,
  44. rules,
  45. } = defineProps({
  46. bgColor: {
  47. type: String,
  48. default: "white",
  49. },
  50. dropdownIcon: {
  51. type: String,
  52. default: "mdi-chevron-down",
  53. },
  54. inputClass: {
  55. type: String,
  56. default: null,
  57. },
  58. label: {
  59. type: String,
  60. default: "",
  61. },
  62. outlined: {
  63. type: Boolean,
  64. default: true,
  65. },
  66. popupContentClass: {
  67. type: String,
  68. default: null,
  69. },
  70. rules: {
  71. type: Array,
  72. default: () => [],
  73. },
  74. });
  75. const attrs = useAttrs();
  76. const model = defineModel({ type: [String, Object, Array, Number, null] });
  77. const error = defineModel("error", {
  78. type: [String, Object, Array, Boolean, null],
  79. });
  80. const selectRef = ref(null);
  81. const required = ref(false);
  82. const selectAttrs = computed(() => {
  83. // eslint-disable-next-line
  84. const { class: _, style: __, ...rest } = attrs;
  85. return rest;
  86. });
  87. const errorMessage = computed(() => {
  88. if (error.value == null) {
  89. return void 0;
  90. }
  91. if (typeof error.value === "boolean") {
  92. return void 0;
  93. }
  94. return String(error.value);
  95. });
  96. onBeforeMount(() => {
  97. rules.forEach((r) => {
  98. if (r?.$id === "required") return (required.value = true);
  99. });
  100. });
  101. defineExpose({
  102. selectRef,
  103. });
  104. </script>
  105. <style scoped>
  106. :deep(.required-field .q-field__label::after) {
  107. color: var(--q-negative);
  108. content: " *";
  109. }
  110. </style>