From e621810f62fc19fea7273c6ef1d741bf9dfd310a Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Fri, 13 Sep 2024 20:39:38 +0200 Subject: [PATCH] fix: vnselect X cancelSignal --- src/components/common/VnSelect.vue | 84 ++++++++++++------- .../components/common/VnSelect.spec.js | 4 +- 2 files changed, 56 insertions(+), 32 deletions(-) diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue index 3b54e43ef..23cec4be6 100644 --- a/src/components/common/VnSelect.vue +++ b/src/components/common/VnSelect.vue @@ -3,8 +3,9 @@ import { ref, toRefs, computed, watch, onMounted } from 'vue'; import { useI18n } from 'vue-i18n'; import { useArrayData } from 'src/composables/useArrayData'; import { useAttrs } from 'vue'; - +// import FetchData from 'src/components/FetchData.vue'; const emit = defineEmits(['update:modelValue', 'update:options', 'remove']); + const $props = defineProps({ modelValue: { type: [String, Number, Object], @@ -93,10 +94,11 @@ const requiredFieldRule = (val) => val ?? t('globals.fieldRequired'); const { optionLabel, optionValue, optionFilter, optionFilterValue, options, modelValue } = toRefs($props); -const myOptions = ref([]); -const myOptionsOriginal = ref([]); +const myOptions = ref($props.options); +const myOptionsOriginal = ref($props.options); const vnSelectRef = ref(); const isLoading = ref(false); +const dataRef = ref(); const lastVal = ref(); const noOneText = t('globals.noOne'); const noOneOpt = ref({ @@ -104,7 +106,6 @@ const noOneOpt = ref({ [optionLabel.value]: noOneText, }); -const useURL = computed(() => $props.url); const selectValue = computed({ get() { return $props.modelValue; @@ -115,22 +116,34 @@ const selectValue = computed({ }, }); +const useURL = computed(() => $props.url); + const $attrs = useAttrs(); const arrayDataKey = - $props.dataKey ?? (useURL.value?.length > 0 ? useURL.value : $attrs.label); + $props.dataKey ?? ($props.url?.length > 0 ? $props.url : $attrs.name ?? $attrs.label); -const arrayData = useArrayData(arrayDataKey, { url: useURL.value }); -const getVal = (val) => ($props.useLike ? { like: `%${val}%` } : val); +const arrayData = useArrayData(arrayDataKey, { url: $props.url }); -watch(modelValue, (newValue) => { - if (!myOptions.value.some((option) => option[optionValue.value] == newValue)) - fetchFilter(newValue); +onMounted(async () => { + if ($props.focusOnMount) setTimeout(() => vnSelectRef.value.showPopup(), 300); + setOptions(options.value); + if (useURL.value) await fetchFilter($props.modelValue); +}); +watch(options, (newValue) => { + setOptions(newValue); }); -onMounted(() => { +watch(modelValue, async (newValue) => { + if (!myOptions.value.some((option) => option[optionValue.value] == newValue)) + await fetchFilter(newValue); + + if ($props.noOne) myOptions.value.unshift(noOneOpt.value); +}); + +onMounted(async () => { setOptions(options.value); - if (useURL.value && $props.modelValue && !findKeyInOptions()) - fetchFilter($props.modelValue); + if ($props.url && $props.modelValue && !findKeyInOptions()) + await fetchFilter($props.modelValue); if ($props.focusOnMount) setTimeout(() => vnSelectRef.value.showPopup(), 300); }); @@ -143,6 +156,7 @@ function setOptions(data, append = true) { myOptions.value = JSON.parse(JSON.stringify(data)); if (append) myOptionsOriginal.value = JSON.parse(JSON.stringify(data)); } + function filter(val, options) { const search = val?.toString()?.toLowerCase(); @@ -163,12 +177,11 @@ function filter(val, options) { return id == search || optionLabel.includes(search); }); } -// const dataRef = ref(); + async function fetchFilter(val) { - if (!useURL.value) return; - - const { fields, sortBy, include, limit } = $props; + if (!$props.url) return; + const { fields, include, sortBy, limit } = $props; const key = optionFilterValue.value ?? (new RegExp(/\d/g).test(val) @@ -184,8 +197,11 @@ async function fetchFilter(val) { }, {}); } else defaultWhere = { [key]: getVal(val) }; const where = { ...(val ? defaultWhere : {}), ...$props.where }; - const fetchOptions = { where, order: sortBy, include, limit }; + const fetchOptions = { where, include, limit }; if (fields) fetchOptions.fields = fields; + if (sortBy) fetchOptions.order = sortBy; + + // return dataRef.value.fetch(fetchOptions); arrayData.store.userParams = $props.params; arrayData.store.userFilter = fetchOptions; arrayData.store.order = fetchOptions.order; @@ -193,7 +209,7 @@ async function fetchFilter(val) { arrayData.store.filter.skip = 0; const { data } = await arrayData.fetch({ append: true, updateRouter: false }); setOptions(data); - return data; + // return data; } async function filterHandler(val, update) { @@ -224,13 +240,19 @@ async function filterHandler(val, update) { ); } +function nullishToTrue(value) { + return value ?? true; +} + +const getVal = (val) => ($props.useLike ? { like: `%${val}%` } : val); + async function onScroll({ to, direction, from, index }) { const lastIndex = myOptions.value.length - 1; if (from === 0 && index === 0) return; - if (!useURL.value) return; + if (!useURL.value && !$props.fetchRef) return; if (direction === 'decrease') return; - if (to === lastIndex && !isLoading.value) { + if (to === lastIndex && arrayData.store.hasMoreData && !isLoading.value) { isLoading.value = true; await arrayData.loadMore(); setOptions(arrayData.store.data); @@ -238,12 +260,19 @@ async function onScroll({ to, direction, from, index }) { isLoading.value = false; } } -function nullishToTrue(value) { - return value ?? true; -}