+ class="absolute z-10 mt-1 w-full bg-white shadow-lg dark:shadow-black dark:bg-gray-700
+ dark:border-gray-600 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm max-h-48"
+ @scroll="handleDropdownScroll">
{
}
};
+const handleDropdownScroll = (event: Event) => {
+ const target = event.target as HTMLElement;
+ const threshold = 10; // pixels from bottom
+
+ if (target.scrollTop + target.clientHeight >= target.scrollHeight - threshold) {
+ emit('scroll-near-end');
+ }
+};
+
onMounted(() => {
updateFromProps();
@@ -247,7 +265,12 @@ onMounted(() => {
});
const filteredItems = computed(() => {
- return props.options.filter(item =>
+
+ if (props.searchDisabled) {
+ return props.options || [];
+ }
+
+ return (props.options || []).filter((item: any) =>
item.label.toLowerCase().includes(search.value.toLowerCase())
);
});
diff --git a/adminforth/spa/src/components/ColumnValueInput.vue b/adminforth/spa/src/components/ColumnValueInput.vue
index d43ad16a..599e6a03 100644
--- a/adminforth/spa/src/components/ColumnValueInput.vue
+++ b/adminforth/spa/src/components/ColumnValueInput.vue
@@ -19,12 +19,26 @@
ref="input"
class="w-full min-w-24"
:options="columnOptions[column.name] || []"
+ :searchDisabled="!column.foreignResource.searchableFields"
+ @scroll-near-end="loadMoreOptions && loadMoreOptions(column.name)"
+ @search="(searchTerm) => {
+ if (column.foreignResource.searchableFields && onSearchInput && onSearchInput[column.name]) {
+ onSearchInput[column.name](searchTerm);
+ }
+ }"
teleportToBody
:placeholder = "columnOptions[column.name]?.length ?$t('Select...'): $t('There are no options available')"
:modelValue="value"
:readonly="(column.editReadonly && source === 'edit') || readonly"
@update:modelValue="$emit('update:modelValue', $event)"
- />
+ >
+
+
+
+ {{ $t('Loading...') }}
+
+
+