From a3891270ea07278db6906c34005c16ddf72e8eb1 Mon Sep 17 00:00:00 2001 From: Ankur Thakur Date: Wed, 27 Aug 2025 21:24:17 -0400 Subject: [PATCH] fix(table): prevent duplicate filter events on delegate reuse Resolves issue where forge-table-filter event fires multiple times based on how many times filter elements have been rendered. This occurred when the same delegate instance was reused and onChange() was called multiple times, accumulating event listeners. The fix adds a flag to prevent attaching multiple onChange listeners to the same delegate instance, ensuring each filter only fires one event regardless of how many times the table is re-rendered. --- src/lib/table/table-utils.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/lib/table/table-utils.ts b/src/lib/table/table-utils.ts index 7379c114c3..391cf3e6af 100644 --- a/src/lib/table/table-utils.ts +++ b/src/lib/table/table-utils.ts @@ -1524,13 +1524,16 @@ export class TableUtils { // If this is a FormFieldComponentDelegate then we can listen for when the value changes, otherwise we just render the custom delegate element if (!!filterListener && delegate instanceof FormFieldComponentDelegate && isFunction(delegate.onChange)) { - if (!isDefined(columnConfig.filterDebounceTime) || isNumber(columnConfig.filterDebounceTime)) { - const debounceTime = isDefined(columnConfig.filterDebounceTime) - ? (columnConfig.filterDebounceTime as number) - : TABLE_CONSTANTS.numbers.DEFAULT_FILTER_DEBOUNCE_TIME; - delegate.onChange(debounce((value: any) => filterListener(value, columnIndex), debounceTime)); - } else { - delegate.onChange((value: any) => filterListener(value, columnIndex)); + if (!(delegate as any).__forgeTableListenerAttached) { + if (!isDefined(columnConfig.filterDebounceTime) || isNumber(columnConfig.filterDebounceTime)) { + const debounceTime = isDefined(columnConfig.filterDebounceTime) + ? (columnConfig.filterDebounceTime as number) + : TABLE_CONSTANTS.numbers.DEFAULT_FILTER_DEBOUNCE_TIME; + delegate.onChange(debounce((value: any) => filterListener(value, columnIndex), debounceTime)); + } else { + delegate.onChange((value: any) => filterListener(value, columnIndex)); + } + (delegate as any).__forgeTableListenerAttached = true; } }