Skip to content

Commit 94eca63

Browse files
committed
fix: select filter model leak
1 parent 2b15bc1 commit 94eca63

File tree

1 file changed

+32
-29
lines changed
  • packages/components-vue/src/components/select

1 file changed

+32
-29
lines changed

packages/components-vue/src/components/select/Filter.vue

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<datalist :id="selectFilterName">
33
<!-- Select is also used as fallback for older browsers -->
44
<SelectSimple
5-
v-model="model"
5+
v-model="selectModel"
66
v-bind="{
77
...$attrs,
88
..._.omit(props, 'modelValue'),
@@ -29,7 +29,7 @@
2929
..._.omit(props, 'modelValue'),
3030
type: 'text',
3131
placeholder: t('select_filter_options'),
32-
disabled: (!!model && !isInvalid) || disabled,
32+
disabled: (!!modelValue && !isInvalid) || disabled,
3333
hidden,
3434
size,
3535
active,
@@ -40,10 +40,10 @@
4040
iconProps,
4141
}"
4242
class="--flx"
43-
@change="handleInputChange"
43+
@change="handleTextInput"
4444
/>
4545
<ActionLink
46-
v-if="model && selectOptions.length > 1"
46+
v-if="modelValue && selectOptions.length > 1"
4747
:theme="theme"
4848
:disabled="disabled"
4949
:aria-label="t('select_restablish_field')"
@@ -57,7 +57,7 @@
5757

5858
<script setup lang="ts">
5959
import type { IconName } from "@fortawesome/fontawesome-common-types";
60-
import { computed, ref, watch } from "vue";
60+
import { computed, ref } from "vue";
6161
import _ from "lodash";
6262
6363
import type { iFormIconProps, iFormOption } from "@open-xamu-co/ui-common-types";
@@ -117,40 +117,46 @@
117117
const selectOptions = computed<iFormOption[]>(() => (props.options ?? []).map(toOption));
118118
const textModel = ref<string | number>("");
119119
/**
120-
* Input model
120+
* Prefers alias instead of value
121121
*/
122-
const model = computed({
122+
const selectModel = computed({
123123
get: () => {
124-
return props.modelValue;
125-
},
126-
set: (newModel) => {
127-
emit("update:model-value", newModel);
124+
const option = selectOptions.value.find(({ value }) => value === props.modelValue);
128125
126+
// alias first
127+
return option?.alias ?? option?.value ?? "";
128+
},
129+
set(valueOrAlias: string | number) {
129130
// look for alias first
130-
const option = selectOptions.value.find(({ value }) => value === newModel);
131+
const option = selectOptions.value.find(({ alias, value }) => {
132+
return alias === valueOrAlias || value === valueOrAlias;
133+
});
131134
132-
if (option) textModel.value = option.alias || option.value;
135+
if (!option) return emit("update:model-value", "");
136+
137+
emit("update:model-value", option.value);
138+
textModel.value = option.alias || option.value;
133139
},
134140
});
135141
const isInvalid = computed<boolean>(() => {
136-
const option = selectOptions.value.find(({ value }) => value === model.value);
142+
const option = selectOptions.value.find(({ value }) => value === props.modelValue);
137143
138-
return (model.value && !option) || props.invalid;
144+
return (props.modelValue && !option) || props.invalid;
139145
});
140146
141147
/**
142148
* Clears up input model
143149
*/
144150
function resetModel() {
145-
model.value = "";
151+
emit("update:model-value", "");
146152
textModel.value = "";
147153
}
148154
149155
/**
150156
* Handle select input
151157
* @listenerOverride select filter requires specific event handling
152158
*/
153-
function handleInputChange(e: Event) {
159+
function handleTextInput(e: Event) {
154160
const { target } = e as Event & { target: HTMLSelectElement };
155161
const deburr = (v: string | number) => _.deburr(String(v)).toLowerCase();
156162
const newModel = deburr(target.value);
@@ -162,21 +168,18 @@
162168
return match === newModel;
163169
});
164170
165-
if (option) model.value = option.value;
166-
else if (model.value) model.value = "";
171+
if (!option) return emit("update:model-value", "");
172+
173+
emit("update:model-value", option.value);
174+
textModel.value = option.alias ?? option.value;
167175
}
168176
169177
// lifecycle
170-
171178
if (isBrowser) supportsDatalist.value = !!HTMLDataListElement;
179+
// Populate text model
180+
if (props.modelValue) {
181+
const option = selectOptions.value.find(({ value }) => value === props.modelValue);
172182
173-
watch(
174-
selectOptions,
175-
(newOptions) => {
176-
const option = newOptions.find(({ value }) => value === props.modelValue);
177-
178-
if (option) textModel.value = option.alias || option.value;
179-
},
180-
{ immediate: true }
181-
);
183+
if (option) textModel.value = option.alias ?? option.value;
184+
}
182185
</script>

0 commit comments

Comments
 (0)