CountrySelect.vue 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <template>
  2. <DefaultSelect
  3. v-model="selectedCountry"
  4. v-bind="$attrs"
  5. use-input
  6. hide-selected
  7. fill-input
  8. clearable
  9. :label
  10. :loading
  11. :placeholder
  12. :options="countryOptions"
  13. @filter="filterFn"
  14. >
  15. <template #no-option>
  16. <q-item>
  17. <q-item-section class="text-grey">
  18. {{ $t("http.errors.no_records_found") }}
  19. </q-item-section>
  20. </q-item>
  21. </template>
  22. </DefaultSelect>
  23. </template>
  24. <script setup>
  25. import { getCountries } from "src/api/country";
  26. import { ref, onMounted } from "vue";
  27. import { useI18n } from "vue-i18n";
  28. import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
  29. const { initialId, placeholder } = defineProps({
  30. initialId: {
  31. type: Number,
  32. required: false,
  33. default: null,
  34. },
  35. placeholder: {
  36. type: String,
  37. default: () =>
  38. useI18n().t("common.actions.search") +
  39. " " +
  40. useI18n().t("ui.navigation.country"),
  41. },
  42. label: {
  43. type: String,
  44. default: () => useI18n().t("ui.navigation.country"),
  45. },
  46. });
  47. const selectedCountry = defineModel({ type: Object });
  48. const loading = ref(true);
  49. const baseCountry = ref([]);
  50. const countries = ref([]);
  51. const countryOptions = ref([]);
  52. const filterFn = async (val, update) => {
  53. const filter = () => {
  54. const needle = val.toLowerCase();
  55. countries.value = baseCountry.value.filter((v) =>
  56. v.name.toLowerCase().includes(needle),
  57. );
  58. countryOptions.value = countries.value.map((country) => ({
  59. label: country.name,
  60. value: country.id,
  61. }));
  62. };
  63. update(filter);
  64. };
  65. const selectCountryByName = (name) => {
  66. if (selectedCountry.value && selectedCountry.value.label === name) return;
  67. selectedCountry.value = countryOptions.value.find(
  68. (country) => country.label === name,
  69. );
  70. };
  71. const selectCountryById = (id) => {
  72. if (selectedCountry.value && selectedCountry.value.id === id) return;
  73. selectedCountry.value = countryOptions.value.find(
  74. (country) => country.value === id,
  75. );
  76. };
  77. onMounted(async () => {
  78. try {
  79. baseCountry.value = await getCountries();
  80. countryOptions.value = baseCountry.value.map((country) => ({
  81. label: country.name,
  82. value: country.id,
  83. }));
  84. if (initialId) {
  85. selectCountryById(initialId);
  86. }
  87. } catch (e) {
  88. console.error(e);
  89. } finally {
  90. loading.value = false;
  91. }
  92. });
  93. defineExpose({
  94. selectCountryByName,
  95. selectCountryById,
  96. });
  97. </script>