Skip to content

Commit

Permalink
[release-2.19] fix: formkit select component not emitting event or up…
Browse files Browse the repository at this point in the history
…dating selection on value change (#6610)

This is an automated cherry-pick of #6602 

/assign LIlGG

```release-note
解决 Formkit Select 组件在值变更时不会发出事件及修改选项值的问题。
```
  • Loading branch information
LIlGG authored Sep 6, 2024
1 parent f538f2f commit dfa10c0
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 25 deletions.
10 changes: 5 additions & 5 deletions ui/src/formkit/inputs/select/SelectContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
import { IconArrowDownLine, IconCloseCircle } from "@halo-dev/components";
import {
computed,
defineEmits,
nextTick,
onMounted,
onUnmounted,
ref,
defineEmits,
type PropType,
onUnmounted,
} from "vue";
import SelectSelector from "./SelectSelector.vue";
import { Dropdown } from "floating-vue";
import MultipleSelectSelector from "./MultipleSelectSelector.vue";
import SelectDropdownContainer from "./SelectDropdownContainer.vue";
import { Dropdown } from "floating-vue";
import SelectSelector from "./SelectSelector.vue";
const props = defineProps({
multiple: {
Expand Down Expand Up @@ -95,7 +95,7 @@ const inputRef = ref<HTMLInputElement | null>();
const searchKeyword = ref<string>("");
const isDropdownVisible = ref<boolean>(false);
const selectedOptions = computed({
get: () => props.selected,
get: () => [...props.selected],
set: (value) => {
emit("update", value);
},
Expand Down
62 changes: 43 additions & 19 deletions ui/src/formkit/inputs/select/SelectMain.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export interface SelectProps {
remoteOptimize?: boolean;
/**
* Allows the creation of new options, only available in local mode.
* Allows the creation of new options, only available in local mode. Default is false.
*/
allowCreate?: boolean;
Expand Down Expand Up @@ -209,7 +209,7 @@ const initSelectProps = () => {
selectProps.maxCount = nodeProps.maxCount ?? NaN;
selectProps.placeholder = nodeProps.placeholder ?? "";
selectProps.action = nodeProps.action ?? "";
selectProps.remoteOptimize = nodeProps.remoteOptimize ?? true;
selectProps.remoteOptimize = !isFalse(nodeProps.remoteOptimize, true);
selectProps.requestOption = {
...{
method: "GET",
Expand All @@ -225,12 +225,12 @@ const initSelectProps = () => {
...(nodeProps.requestOption ?? {}),
};
selectProps.multiple = !isFalse(nodeProps.multiple);
selectProps.sortable = !isFalse(nodeProps.sortable);
selectProps.sortable = !isFalse(nodeProps.sortable, true);
selectProps.remote = !isFalse(nodeProps.remote);
selectProps.allowCreate = !isFalse(nodeProps.allowCreate);
selectProps.clearable = !isFalse(nodeProps.clearable);
selectProps.searchable = !isFalse(nodeProps.searchable);
selectProps.autoSelect = !isFalse(nodeProps.autoSelect) || true;
selectProps.autoSelect = !isFalse(nodeProps.autoSelect, true);
if (selectProps.remote) {
if (!nodeProps.remoteOption) {
throw new Error("remoteOption is required when remote is true.");
Expand Down Expand Up @@ -543,14 +543,25 @@ const getAutoSelectedOption = ():
});
};
const stopSelectedWatch = watch(
() => [options.value, props.context.value],
async () => {
if (options.value) {
watch(
() => props.context.value,
async (newValue) => {
const selectedValues = selectOptions.value?.map((item) => item.value) || [];
if (selectedValues.length > 0 && selectedValues.includes(newValue)) {
return;
}
const selectedOption = await fetchSelectedOptions();
selectOptions.value = selectedOption;
}
);
watch(
() => options.value,
async (newOptions) => {
if (newOptions && newOptions.length > 0) {
const selectedOption = await fetchSelectedOptions();
if (selectedOption) {
selectOptions.value = selectedOption;
return;
}
const isAutoSelect =
selectProps.autoSelect &&
Expand All @@ -562,12 +573,12 @@ const stopSelectedWatch = watch(
// Automatically select the first option when the selected value is empty.
const autoSelectedOption = getAutoSelectedOption();
if (autoSelectedOption) {
selectOptions.value = [autoSelectedOption];
handleUpdate(selectOptions.value);
handleUpdate([autoSelectedOption]);
}
}
}
}
},
{ once: true }
);
// When attr options are processed asynchronously, it is necessary to monitor
Expand All @@ -581,14 +592,27 @@ watch(
}
);
const handleSelectedUpdate = (
value: Array<{ label: string; value: string }>
) => {
stopSelectedWatch();
handleUpdate(value);
const handleUpdate = async (value: Array<{ label: string; value: string }>) => {
const oldSelectValue = selectOptions.value;
if (
oldSelectValue &&
value.length === oldSelectValue.length &&
value.every((item, index) => item.value === oldSelectValue[index].value)
) {
return;
}
const newValue = value.map((item) => {
return {
label: item.label,
value: item.value,
};
});
handleSetNodeValue(newValue);
await props.context.node.settled;
props.context.attrs.onChange?.(newValue);
};
const handleUpdate = (value: Array<{ label: string; value: string }>) => {
const handleSetNodeValue = (value: Array<{ label: string; value: string }>) => {
const values = value.map((item) => item.value);
selectOptions.value = value;
if (selectProps.multiple) {
Expand Down Expand Up @@ -725,7 +749,7 @@ const handleNextPage = async () => {
:clearable="selectProps.clearable"
:searchable="selectProps.searchable"
:auto-select="selectProps.autoSelect"
@update="handleSelectedUpdate"
@update="handleUpdate"
@search="handleSearch"
@load-more="handleNextPage"
/>
Expand Down
6 changes: 5 additions & 1 deletion ui/src/formkit/inputs/select/isFalse.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export const isFalse = (value: string | boolean | undefined | null) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isFalse = (value: any, onlyBoolean = false) => {
if (onlyBoolean) {
return [false, "false"].includes(value);
}
return [undefined, null, "false", false].includes(value);
};

0 comments on commit dfa10c0

Please sign in to comment.