diff --git a/packages/pluggableWidgets/combobox-web/CHANGELOG.md b/packages/pluggableWidgets/combobox-web/CHANGELOG.md
index b43c5de8aa..3007958889 100644
--- a/packages/pluggableWidgets/combobox-web/CHANGELOG.md
+++ b/packages/pluggableWidgets/combobox-web/CHANGELOG.md
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
## [Unreleased]
+### Changed
+
+- Moved the debounce interval for filtering operations from the Events tab to Advanced tab.
+
## [2.5.1] - 2025-09-19
### Fixed
@@ -15,6 +19,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- We fixed an issue where combobox lazy load is not working on initial load.
+### Added
+
+- We added the option to configure a debounce interval for datasource filter operations as well.
+
## [2.5.0] - 2025-08-12
### Added
diff --git a/packages/pluggableWidgets/combobox-web/src/Combobox.editorConfig.ts b/packages/pluggableWidgets/combobox-web/src/Combobox.editorConfig.ts
index 7e7c05e751..392b732415 100644
--- a/packages/pluggableWidgets/combobox-web/src/Combobox.editorConfig.ts
+++ b/packages/pluggableWidgets/combobox-web/src/Combobox.editorConfig.ts
@@ -178,10 +178,6 @@ export function getProperties(
hidePropertiesIn(defaultProperties, values, ["loadingType"]);
}
- if (values.onChangeFilterInputEvent === null) {
- hidePropertiesIn(defaultProperties, values, ["filterInputDebounceInterval"]);
- }
-
return defaultProperties;
}
diff --git a/packages/pluggableWidgets/combobox-web/src/Combobox.xml b/packages/pluggableWidgets/combobox-web/src/Combobox.xml
index c1994358df..274e3ba9af 100644
--- a/packages/pluggableWidgets/combobox-web/src/Combobox.xml
+++ b/packages/pluggableWidgets/combobox-web/src/Combobox.xml
@@ -329,7 +329,6 @@
On leave
-
On filter input change
@@ -337,10 +336,6 @@
-
- Debounce interval
- The debounce interval for each filter input change event triggered in milliseconds.
-
@@ -439,6 +434,10 @@
None
+
+ Debounce interval
+ The debounce interval for each filter input change event triggered in milliseconds.
+
diff --git a/packages/pluggableWidgets/combobox-web/src/helpers/Association/BaseAssociationSelector.ts b/packages/pluggableWidgets/combobox-web/src/helpers/Association/BaseAssociationSelector.ts
index eb910d4a4e..a4e65f8c16 100644
--- a/packages/pluggableWidgets/combobox-web/src/helpers/Association/BaseAssociationSelector.ts
+++ b/packages/pluggableWidgets/combobox-web/src/helpers/Association/BaseAssociationSelector.ts
@@ -27,9 +27,9 @@ export class BaseAssociationSelector = new Map();
private lazyLoader: LazyLoadProvider = new LazyLoadProvider();
- constructor() {
+ constructor(props: { filterInputDebounceInterval: number }) {
this.caption = new AssociationSimpleCaptionsProvider(this._valuesMap);
- this.options = new AssociationOptionsProvider(this.caption, this._valuesMap);
+ this.options = new AssociationOptionsProvider(this.caption, this._valuesMap, props.filterInputDebounceInterval);
}
updateProps(props: ComboboxContainerProps): void {
diff --git a/packages/pluggableWidgets/combobox-web/src/helpers/Association/utils.ts b/packages/pluggableWidgets/combobox-web/src/helpers/Association/utils.ts
index ac0e0a99f2..1cc1e97959 100644
--- a/packages/pluggableWidgets/combobox-web/src/helpers/Association/utils.ts
+++ b/packages/pluggableWidgets/combobox-web/src/helpers/Association/utils.ts
@@ -28,13 +28,15 @@ type ExtractionReturnValue = [
ListWidgetValue | undefined,
OptionsSourceAssociationCustomContentTypeEnum,
boolean,
- LoadingTypeEnum
+ LoadingTypeEnum,
+ number
];
export function extractAssociationProps(props: ComboboxContainerProps): ExtractionReturnValue {
const attr = props.attributeAssociation;
const filterType = props.filterType;
const onChangeEvent = props.onChangeEvent;
+ const filterInputDebounceInterval = props.filterInputDebounceInterval;
if (!attr) {
throw new Error("'optionsSourceType' type is 'association' but 'attributeAssociation' is not defined.");
@@ -79,6 +81,7 @@ export function extractAssociationProps(props: ComboboxContainerProps): Extracti
customContent,
customContentType,
lazyLoading,
- loadingType
+ loadingType,
+ filterInputDebounceInterval
];
}
diff --git a/packages/pluggableWidgets/combobox-web/src/helpers/BaseDatasourceOptionsProvider.ts b/packages/pluggableWidgets/combobox-web/src/helpers/BaseDatasourceOptionsProvider.ts
index 1fbd1ae76a..9d2bb92632 100644
--- a/packages/pluggableWidgets/combobox-web/src/helpers/BaseDatasourceOptionsProvider.ts
+++ b/packages/pluggableWidgets/combobox-web/src/helpers/BaseDatasourceOptionsProvider.ts
@@ -1,27 +1,38 @@
+import { debounce } from "@mendix/widget-plugin-platform/utils/debounce";
import { ListAttributeValue, ListValue, ObjectItem } from "mendix";
import { FilterTypeEnum } from "../../typings/ComboboxProps";
import { BaseOptionsProvider } from "./BaseOptionsProvider";
import { datasourceFilter } from "./datasourceFilter";
import { CaptionsProvider, SortOrder, Status } from "./types";
import { DEFAULT_LIMIT_SIZE } from "./utils";
+import { FilterCondition } from "mendix/filters";
export interface BaseProps {
attributeId?: ListAttributeValue["id"];
ds: ListValue;
filterType: FilterTypeEnum;
lazyLoading: boolean;
+ filterInputDebounceInterval?: number;
}
export class BaseDatasourceOptionsProvider extends BaseOptionsProvider {
private ds?: ListValue;
private attributeId?: ListAttributeValue["id"];
protected loading: boolean = false;
+ private debouncedSetFilter: (filterCondition: FilterCondition | undefined) => void;
constructor(
caption: CaptionsProvider,
- protected valuesMap: Map
+ protected valuesMap: Map,
+ filterInputDebounceInterval: number = 200
) {
super(caption);
+
+ const [debouncedFn] = debounce((filterCondition: FilterCondition | undefined) => {
+ this.ds?.setFilter(filterCondition);
+ }, filterInputDebounceInterval);
+
+ this.debouncedSetFilter = debouncedFn;
}
get sortOrder(): SortOrder {
@@ -51,10 +62,10 @@ export class BaseDatasourceOptionsProvider extends BaseOptionsProvider = new Map();
selectedItemsSorting: SelectedItemsSortingEnum = "none";
- constructor() {
+ constructor(props: { filterInputDebounceInterval: number }) {
this.caption = new DatabaseCaptionsProvider(this._objectsMap);
- this.options = new DatabaseOptionsProvider(this.caption, this._objectsMap);
+ this.options = new DatabaseOptionsProvider(this.caption, this._objectsMap, props.filterInputDebounceInterval);
}
getOptions(): string[] {
diff --git a/packages/pluggableWidgets/combobox-web/src/helpers/Database/DatabaseSingleSelectionSelector.ts b/packages/pluggableWidgets/combobox-web/src/helpers/Database/DatabaseSingleSelectionSelector.ts
index d480133072..55944a48fe 100644
--- a/packages/pluggableWidgets/combobox-web/src/helpers/Database/DatabaseSingleSelectionSelector.ts
+++ b/packages/pluggableWidgets/combobox-web/src/helpers/Database/DatabaseSingleSelectionSelector.ts
@@ -33,9 +33,9 @@ export class DatabaseSingleSelectionSelector | undefined;
+ filterInputDebounceInterval: number;
};
export function extractDatabaseProps(props: ComboboxContainerProps): ExtractionReturnValue {
const targetAttribute = props.databaseAttributeString;
const filterType = props.filterType;
-
+ const filterInputDebounceInterval = props.filterInputDebounceInterval;
const ds = props.optionsSourceDatabaseDataSource;
if (!ds) {
throw new Error("'optionsSourceType' type is 'database' but 'optionsSourceDatabaseDataSource' is not defined.");
@@ -83,7 +84,8 @@ export function extractDatabaseProps(props: ComboboxContainerProps): ExtractionR
filterType,
lazyLoading,
loadingType,
- valueSourceAttribute
+ valueSourceAttribute,
+ filterInputDebounceInterval
};
}
diff --git a/packages/pluggableWidgets/combobox-web/src/helpers/getSelector.ts b/packages/pluggableWidgets/combobox-web/src/helpers/getSelector.ts
index 7bc6005f66..4667dc363c 100644
--- a/packages/pluggableWidgets/combobox-web/src/helpers/getSelector.ts
+++ b/packages/pluggableWidgets/combobox-web/src/helpers/getSelector.ts
@@ -13,16 +13,20 @@ export function getSelector(props: ComboboxContainerProps): Selector {
return new EnumBooleanSingleSelector();
} else if (props.optionsSourceType === "association") {
return props.attributeAssociation.type === "Reference"
- ? new AssociationSingleSelector()
- : new AssociationMultiSelector();
+ ? new AssociationSingleSelector({ filterInputDebounceInterval: props.filterInputDebounceInterval })
+ : new AssociationMultiSelector({ filterInputDebounceInterval: props.filterInputDebounceInterval });
} else {
throw new Error(`'optionsSourceType' of type '${props.optionsSourceType}' is not supported`);
}
} else if (props.source === "database") {
if (props.optionsSourceDatabaseItemSelection?.type === "Multi") {
- return new DatabaseMultiSelectionSelector();
+ return new DatabaseMultiSelectionSelector({
+ filterInputDebounceInterval: props.filterInputDebounceInterval
+ });
} else {
- return new DatabaseSingleSelectionSelector();
+ return new DatabaseSingleSelectionSelector({
+ filterInputDebounceInterval: props.filterInputDebounceInterval
+ });
}
} else if (props.source === "static") {
return new StaticSingleSelector();
diff --git a/packages/pluggableWidgets/combobox-web/typings/ComboboxProps.d.ts b/packages/pluggableWidgets/combobox-web/typings/ComboboxProps.d.ts
index aec3e503fb..fcc265d859 100644
--- a/packages/pluggableWidgets/combobox-web/typings/ComboboxProps.d.ts
+++ b/packages/pluggableWidgets/combobox-web/typings/ComboboxProps.d.ts
@@ -90,7 +90,6 @@ export interface ComboboxContainerProps {
onEnterEvent?: ActionValue;
onLeaveEvent?: ActionValue;
onChangeFilterInputEvent?: ActionValue<{ filterInput: Option }>;
- filterInputDebounceInterval: number;
ariaRequired: DynamicValue;
ariaLabel?: DynamicValue;
clearButtonAriaLabel?: DynamicValue;
@@ -102,6 +101,7 @@ export interface ComboboxContainerProps {
loadingType: LoadingTypeEnum;
selectedItemsSorting: SelectedItemsSortingEnum;
filterType: FilterTypeEnum;
+ filterInputDebounceInterval: number;
}
export interface ComboboxPreviewProps {
@@ -148,7 +148,6 @@ export interface ComboboxPreviewProps {
onEnterEvent: {} | null;
onLeaveEvent: {} | null;
onChangeFilterInputEvent: {} | null;
- filterInputDebounceInterval: number | null;
ariaRequired: string;
ariaLabel: string;
clearButtonAriaLabel: string;
@@ -160,4 +159,5 @@ export interface ComboboxPreviewProps {
loadingType: LoadingTypeEnum;
selectedItemsSorting: SelectedItemsSortingEnum;
filterType: FilterTypeEnum;
+ filterInputDebounceInterval: number | null;
}