From 5d8090c0a014339a1f28c6d8920a8fb459d017f7 Mon Sep 17 00:00:00 2001 From: raizasafeel <89463672+raizasafeel@users.noreply.github.com> Date: Tue, 17 Mar 2026 00:16:13 +0530 Subject: [PATCH] fix(controls): link and multiselect filter handling --- frontend/src/components/Controls/Link.vue | 4 +- .../src/components/Controls/MultiSelect.vue | 63 ++++++++++--------- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/frontend/src/components/Controls/Link.vue b/frontend/src/components/Controls/Link.vue index 6d73dbaf..a797c8b1 100644 --- a/frontend/src/components/Controls/Link.vue +++ b/frontend/src/components/Controls/Link.vue @@ -140,7 +140,7 @@ const options = createResource({ params: { txt: text.value, doctype: props.doctype, - filters: props.filters, + filters: JSON.stringify(props.filters), }, transform: (data) => { return data.map((option) => { @@ -158,7 +158,7 @@ const reload = (val) => { params: { txt: val, doctype: props.doctype, - filters: props.filters, + filters: JSON.stringify(props.filters), }, }) options.reload() diff --git a/frontend/src/components/Controls/MultiSelect.vue b/frontend/src/components/Controls/MultiSelect.vue index ba7261aa..41b9c051 100644 --- a/frontend/src/components/Controls/MultiSelect.vue +++ b/frontend/src/components/Controls/MultiSelect.vue @@ -10,6 +10,7 @@ ref="search" class="form-input w-full focus-visible:!ring-0" type="text" + :displayValue="() => query" @change=" (e) => { query = e.target.value @@ -106,7 +107,7 @@ import { ComboboxOptions, ComboboxOption, } from '@headlessui/vue' -import { createResource, Button } from 'frappe-ui' +import { createResource, Button, toast } from 'frappe-ui' import { ref, computed, useAttrs, watch } from 'vue' import { watchDebounced } from '@vueuse/core' import { X, Plus } from 'lucide-vue-next' @@ -115,7 +116,9 @@ const props = defineProps({ label: String, size: { type: String, default: 'sm' }, doctype: { type: String, required: true }, - filters: { type: Object, default: () => ({}) }, + filters: { type: [Object, Array], default: () => ({}) }, + url: { type: String, default: 'frappe.desk.search.search_link' }, + searchParams: { type: Object, default: () => ({}) }, validate: Function, errorMessage: { type: Function, @@ -124,22 +127,18 @@ const props = defineProps({ required: Boolean, }) -const values = defineModel() +const values = defineModel({ default: () => [] }) const attrs = useAttrs() const trigger = ref(null) const query = ref('') const text = ref('') const selectedValue = ref(null) -const error = ref(null) - -const emit = defineEmits(['update:modelValue']) watch(selectedValue, (val) => { if (!val?.value) return query.value = '' addValue(val.value) selectedValue.value = null - emit('update:modelValue', values.value) }) watchDebounced( @@ -153,14 +152,27 @@ watchDebounced( { debounce: 300, immediate: true } ) -const filterOptions = createResource({ - url: 'frappe.desk.search.search_link', - method: 'POST', - auto: true, - params: { - txt: text.value, - doctype: props.doctype, +// Refetch when filters or searchParams change +watch( + () => [props.filters, props.searchParams], + () => { + reload(text.value) }, + { deep: true } +) + +function getParams(txt) { + return { + txt, + doctype: props.doctype, + filters: JSON.stringify(props.filters), + ...props.searchParams, + } +} + +const filterOptions = createResource({ + url: props.url, + method: 'POST', }) const options = computed(() => { @@ -170,10 +182,7 @@ const options = computed(() => { function reload(val) { filterOptions.update({ - params: { - txt: val, - doctype: props.doctype, - }, + params: getParams(val), }) filterOptions.reload() } @@ -186,34 +195,30 @@ function onFocus() { } function addValue(value) { - error.value = null - if (!value) return const splitValues = value.split(',') + let newValues = [...(values.value || [])] splitValues.forEach((val) => { val = val.trim() if (!val) return - if (values.value?.includes(val)) return + if (newValues.includes(val)) return if (props.validate && !props.validate(val)) { - error.value = props.errorMessage(val) + toast.error(props.errorMessage(val)) return } - if (!values.value) values.value = [val] - else values.value.push(val) + newValues.push(val) }) + + values.value = newValues } function removeValue(value) { - let indexToRemove = values.value.indexOf(value) - if (indexToRemove > -1) { - values.value.splice(indexToRemove, 1) - } - emit('update:modelValue', values.value) + values.value = values.value.filter((v) => v !== value) } const labelClasses = computed(() => [