diff --git a/packages/common/src/filters/compoundDateFilter.ts b/packages/common/src/filters/compoundDateFilter.ts
index 31532d7f4..014bc6fd2 100644
--- a/packages/common/src/filters/compoundDateFilter.ts
+++ b/packages/common/src/filters/compoundDateFilter.ts
@@ -140,12 +140,8 @@ export class CompoundDateFilter implements Filter {
destroyObjectDomElementProps(this.flatInstance);
}
}
- if (this._filterElm) {
- this._filterElm.remove();
- }
- if (this._selectOperatorElm) {
- this._selectOperatorElm.remove();
- }
+ this._filterElm?.remove?.();
+ this._selectOperatorElm?.remove?.();
}
hide() {
@@ -225,14 +221,16 @@ export class CompoundDateFilter implements Filter {
};
// add the time picker when format is UTC (Z) or has the 'h' (meaning hours)
- if (outputFormat && (outputFormat === 'Z' || outputFormat.toLowerCase().indexOf('h') > -1)) {
+ if (outputFormat && (outputFormat === 'Z' || outputFormat.toLowerCase().includes('h'))) {
pickerOptions.enableTime = true;
}
// merge options with optional user's custom options
this._flatpickrOptions = { ...pickerOptions, ...userFilterOptions };
- let placeholder = (this.gridOptions) ? (this.gridOptions.defaultFilterPlaceholder || '') : '';
- if (this.columnFilter && this.columnFilter.placeholder) {
+
+ // create the DOM element & add an ID and filter class
+ let placeholder = this.gridOptions?.defaultFilterPlaceholder ?? '';
+ if (this.columnFilter?.placeholder) {
placeholder = this.columnFilter.placeholder;
}
diff --git a/packages/common/src/filters/compoundInputFilter.ts b/packages/common/src/filters/compoundInputFilter.ts
index 71b0823b0..c9660df2e 100644
--- a/packages/common/src/filters/compoundInputFilter.ts
+++ b/packages/common/src/filters/compoundInputFilter.ts
@@ -11,18 +11,20 @@ import {
OperatorDetail,
SlickGrid,
} from '../interfaces/index';
-import { buildSelectOperatorHtmlString } from './filterUtilities';
-import { getTranslationPrefix, mapOperatorToShorthandDesignation } from '../services/utilities';
+import { buildSelectOperator } from './filterUtilities';
+import { emptyElement, getTranslationPrefix, mapOperatorToShorthandDesignation } from '../services/utilities';
+import { BindingEventService } from '../services/bindingEvent.service';
import { TranslaterService } from '../services/translater.service';
export class CompoundInputFilter implements Filter {
+ protected _bindEventService: BindingEventService;
protected _clearFilterTriggered = false;
protected _debounceTypingDelay = 0;
protected _shouldTriggerQuery = true;
protected _inputType = 'text';
- protected $filterElm: any;
- protected $filterInputElm: any;
- protected $selectOperatorElm: any;
+ protected _filterElm!: HTMLDivElement;
+ protected _filterInputElm!: HTMLInputElement;
+ protected _selectOperatorElm!: HTMLSelectElement;
protected _operator?: OperatorType | OperatorString;
grid!: SlickGrid;
searchTerms: SearchTerm[] = [];
@@ -30,14 +32,16 @@ export class CompoundInputFilter implements Filter {
callback!: FilterCallback;
timer?: NodeJS.Timeout;
- constructor(protected readonly translaterService: TranslaterService) { }
+ constructor(protected readonly translaterService: TranslaterService) {
+ this._bindEventService = new BindingEventService();
+ }
/** Getter for the Grid Options pulled through the Grid Object */
protected get gridOptions(): GridOption {
return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {};
}
- /** Getter for the Filter Operator */
+ /** Getter for the Column Filter */
get columnFilter(): ColumnFilter {
return this.columnDef && this.columnDef.filter || {};
}
@@ -83,7 +87,7 @@ export class CompoundInputFilter implements Filter {
this.grid = args.grid;
this.callback = args.callback;
this.columnDef = args.columnDef;
- this.operator = args.operator || '';
+ this.operator = args.operator as OperatorString;
this.searchTerms = (args.hasOwnProperty('searchTerms') ? args.searchTerms : []) || [];
// analyze if we have any keyboard debounce delay (do we wait for user to finish typing before querying)
@@ -96,25 +100,25 @@ export class CompoundInputFilter implements Filter {
// step 1, create the DOM Element of the filter which contain the compound Operator+Input
// and initialize it if searchTerm is filled
- this.$filterElm = this.createDomElement(searchTerm);
+ this._filterElm = this.createDomElement(searchTerm);
- // step 3, subscribe to the input change event and run the callback when that happens
+ // step 3, subscribe to the keyup event and run the callback when that happens
// also add/remove "filled" class for styling purposes
// we'll use all necessary events to cover the following (keyup, change, mousewheel & spinner)
- this.$filterInputElm.on('keyup blur change wheel', this.onTriggerEvent.bind(this));
- this.$selectOperatorElm.on('change', this.onTriggerEvent.bind(this));
+ this._bindEventService.bind(this._filterInputElm, ['keyup', 'blur', 'change', 'wheel'], this.onTriggerEvent.bind(this));
+ this._bindEventService.bind(this._selectOperatorElm, 'change', this.onTriggerEvent.bind(this));
}
/**
* Clear the filter value
*/
clear(shouldTriggerQuery = true) {
- if (this.$filterElm && this.$selectOperatorElm) {
+ if (this._filterElm && this._selectOperatorElm) {
this._clearFilterTriggered = true;
this._shouldTriggerQuery = shouldTriggerQuery;
this.searchTerms = [];
- this.$selectOperatorElm.val(0);
- this.$filterInputElm.val('');
+ this._selectOperatorElm.value = '';
+ this._filterInputElm.value = '';
this.onTriggerEvent(undefined);
}
}
@@ -123,26 +127,23 @@ export class CompoundInputFilter implements Filter {
* destroy the filter
*/
destroy() {
- if (this.$filterElm && this.$selectOperatorElm) {
- this.$filterElm.off('keyup blur change wheel').remove();
- this.$selectOperatorElm.off('change');
- }
- this.$filterElm = null;
- this.$selectOperatorElm = null;
+ this._bindEventService.unbindAll();
+ this._filterElm?.remove?.();
+ this._selectOperatorElm?.remove?.();
}
- /** Set value(s) on the DOM element */
+ /** Set value(s) on the DOM element */
setValues(values: SearchTerm[] | SearchTerm, operator?: OperatorType | OperatorString) {
if (values) {
const newValue = Array.isArray(values) ? values[0] : values;
- this.$filterInputElm.val(newValue);
+ this._filterInputElm.value = `${newValue ?? ''}`;
}
// set the operator, in the DOM as well, when defined
this.operator = operator || this.defaultOperator;
- if (operator && this.$selectOperatorElm) {
+ if (operator && this._selectOperatorElm) {
const operatorShorthand = mapOperatorToShorthandDesignation(this.operator);
- this.$selectOperatorElm.val(operatorShorthand);
+ this._selectOperatorElm.value = operatorShorthand;
}
}
@@ -150,13 +151,23 @@ export class CompoundInputFilter implements Filter {
// protected functions
// ------------------
- protected buildInputHtmlString() {
+ protected buildInputElement(): HTMLInputElement {
const columnId = this.columnDef?.id ?? '';
- let placeholder = (this.gridOptions) ? (this.gridOptions.defaultFilterPlaceholder || '') : '';
- if (this.columnFilter && this.columnFilter.placeholder) {
+
+ // create the DOM element & add an ID and filter class
+ let placeholder = this.gridOptions?.defaultFilterPlaceholder ?? '';
+ if (this.columnFilter?.placeholder) {
placeholder = this.columnFilter.placeholder;
}
- return ``;
+
+ const inputElm = document.createElement('input');
+ inputElm.type = this._inputType || 'text';
+ inputElm.className = `form-control compound-input filter-${columnId}`;
+ inputElm.autocomplete = 'off';
+ inputElm.placeholder = placeholder;
+ inputElm.setAttribute('role', 'presentation');
+
+ return inputElm;
}
/** Get the available operator option values to populate the operator select dropdown list */
@@ -212,16 +223,22 @@ export class CompoundInputFilter implements Filter {
*/
protected createDomElement(searchTerm?: SearchTerm) {
const columnId = this.columnDef?.id ?? '';
- const $headerElm = this.grid.getHeaderRowColumn(columnId);
- $($headerElm).empty();
+ const headerElm = this.grid.getHeaderRowColumn(columnId);
+ emptyElement(headerElm);
// create the DOM Select dropdown for the Operator
- const selectOperatorHtmlString = buildSelectOperatorHtmlString(this.getOperatorOptionValues());
- this.$selectOperatorElm = $(selectOperatorHtmlString);
- this.$filterInputElm = $(this.buildInputHtmlString());
- const $filterContainerElm = $(`
`);
- const $containerInputGroup = $(``);
- const $operatorInputGroupAddon = $(``);
+ this._selectOperatorElm = buildSelectOperator(this.getOperatorOptionValues());
+ this._filterInputElm = this.buildInputElement();
+ const emptySpanElm = document.createElement('span');
+
+ const filterContainerElm = document.createElement('div');
+ filterContainerElm.className = `form-group search-filter filter-${columnId}`;
+
+ const containerInputGroupElm = document.createElement('div');
+ containerInputGroupElm.className = 'input-group';
+
+ const operatorInputGroupAddonElm = document.createElement('div');
+ operatorInputGroupAddonElm.className = 'input-group-addon input-group-prepend operator';
/* the DOM element final structure will be
@@ -231,54 +248,55 @@ export class CompoundInputFilter implements Filter {
*/
- $operatorInputGroupAddon.append(this.$selectOperatorElm);
- $containerInputGroup.append($operatorInputGroupAddon);
- $containerInputGroup.append(this.$filterInputElm);
+ operatorInputGroupAddonElm.appendChild(this._selectOperatorElm);
+ containerInputGroupElm.appendChild(operatorInputGroupAddonElm);
+ containerInputGroupElm.appendChild(this._filterInputElm);
+ containerInputGroupElm.appendChild(emptySpanElm);
// create the DOM element & add an ID and filter class
- $filterContainerElm.append($containerInputGroup);
+ filterContainerElm.appendChild(containerInputGroupElm);
- this.$filterInputElm.val(searchTerm);
- this.$filterInputElm.data('columnId', columnId);
+ this._filterInputElm.value = `${searchTerm ?? ''}`;
+ this._filterInputElm.dataset.columnid = `${columnId}`;
if (this.operator) {
const operatorShorthand = mapOperatorToShorthandDesignation(this.operator);
- this.$selectOperatorElm.val(operatorShorthand);
+ this._selectOperatorElm.value = operatorShorthand;
}
// if there's a search term, we will add the "filled" class for styling purposes
if (searchTerm) {
- $filterContainerElm.addClass('filled');
+ this._filterInputElm.classList.add('filled');
}
// append the new DOM element to the header row
- if ($filterContainerElm && typeof $filterContainerElm.appendTo === 'function') {
- $filterContainerElm.appendTo($headerElm);
+ if (filterContainerElm) {
+ headerElm.appendChild(filterContainerElm);
}
- return $filterContainerElm;
+ return filterContainerElm;
}
/**
* Event trigger, could be called by the Operator dropdown or the input itself and we will cover the following (keyup, change, mousewheel & spinner)
* We will trigger the Filter Service callback from this handler
*/
- protected onTriggerEvent(event: KeyboardEvent | undefined) {
+ protected onTriggerEvent(event: Event | undefined) {
if (this._clearFilterTriggered) {
this.callback(event, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery });
- this.$filterElm.removeClass('filled');
+ this._filterElm.classList.remove('filled');
} else {
const eventType = event?.type ?? '';
- const selectedOperator = this.$selectOperatorElm.find('option:selected').val();
- let value = this.$filterInputElm.val() as string;
+ const selectedOperator = this._selectOperatorElm.value as OperatorString;
+ let value = this._filterInputElm.value as string;
const enableWhiteSpaceTrim = this.gridOptions.enableFilterTrimWhiteSpace || this.columnFilter.enableTrimWhiteSpace;
if (typeof value === 'string' && enableWhiteSpaceTrim) {
value = value.trim();
}
- (value !== null && value !== undefined && value !== '') ? this.$filterElm.addClass('filled') : this.$filterElm.removeClass('filled');
- const callbackArgs = { columnDef: this.columnDef, searchTerms: (value ? [value] : null), operator: selectedOperator || '', shouldTriggerQuery: this._shouldTriggerQuery };
- const typingDelay = (eventType === 'keyup' && event?.key !== 'Enter') ? this._debounceTypingDelay : 0;
+ (value !== null && value !== undefined && value !== '') ? this._filterElm.classList.add('filled') : this._filterElm.classList.remove('filled');
+ const callbackArgs = { columnDef: this.columnDef, searchTerms: (value ? [value] : null), operator: selectedOperator, shouldTriggerQuery: this._shouldTriggerQuery };
+ const typingDelay = (eventType === 'keyup' && (event as KeyboardEvent)?.key !== 'Enter') ? this._debounceTypingDelay : 0;
if (typingDelay > 0) {
clearTimeout(this.timer as NodeJS.Timeout);
diff --git a/packages/common/src/filters/dateRangeFilter.ts b/packages/common/src/filters/dateRangeFilter.ts
index 254787a62..6ccfc4bbc 100644
--- a/packages/common/src/filters/dateRangeFilter.ts
+++ b/packages/common/src/filters/dateRangeFilter.ts
@@ -132,9 +132,7 @@ export class DateRangeFilter implements Filter {
destroyObjectDomElementProps(this.flatInstance);
}
}
- if (this._filterElm) {
- this._filterElm.remove();
- }
+ this._filterElm?.remove?.();
}
hide() {
diff --git a/packages/common/src/filters/inputFilter.ts b/packages/common/src/filters/inputFilter.ts
index f5099efe3..a023d843a 100644
--- a/packages/common/src/filters/inputFilter.ts
+++ b/packages/common/src/filters/inputFilter.ts
@@ -8,20 +8,25 @@ import {
SlickGrid,
} from '../interfaces/index';
import { OperatorType, OperatorString, SearchTerm } from '../enums/index';
+import { BindingEventService } from '../services/bindingEvent.service';
+import { emptyElement } from '../services';
export class InputFilter implements Filter {
+ protected _bindEventService: BindingEventService;
protected _clearFilterTriggered = false;
protected _debounceTypingDelay = 0;
protected _shouldTriggerQuery = true;
protected _inputType = 'text';
protected _timer?: NodeJS.Timeout;
- protected $filterElm: any;
+ protected _filterElm!: HTMLInputElement;
grid!: SlickGrid;
searchTerms: SearchTerm[] = [];
columnDef!: Column;
callback!: FilterCallback;
- constructor() { }
+ constructor() {
+ this._bindEventService = new BindingEventService();
+ }
/** Getter for the Column Filter */
get columnFilter(): ColumnFilter {
@@ -80,28 +85,25 @@ export class InputFilter implements Filter {
// filter input can only have 1 search term, so we will use the 1st array index if it exist
const searchTerm = (Array.isArray(this.searchTerms) && this.searchTerms.length >= 0) ? this.searchTerms[0] : '';
- // step 1, create HTML string template
- const filterTemplate = this.buildTemplateHtmlString();
-
- // step 2, create the DOM Element of the filter & initialize it if searchTerm is filled
- this.$filterElm = this.createDomElement(filterTemplate, searchTerm);
+ // step 1, create the DOM Element of the filter & initialize it if searchTerm is filled
+ this._filterElm = this.createDomElement(searchTerm);
- // step 3, subscribe to the input event and run the callback when that happens
+ // step 2, subscribe to the input event and run the callback when that happens
// also add/remove "filled" class for styling purposes
// we'll use all necessary events to cover the following (keyup, change, mousewheel & spinner)
- this.$filterElm.on('keyup blur change wheel', this.handleInputChange.bind(this));
+ this._bindEventService.bind(this._filterElm, ['keyup', 'blur', 'change', 'wheel'], this.handleInputChange.bind(this));
}
/**
* Clear the filter value
*/
clear(shouldTriggerQuery = true) {
- if (this.$filterElm) {
+ if (this._filterElm) {
this._clearFilterTriggered = true;
this._shouldTriggerQuery = shouldTriggerQuery;
this.searchTerms = [];
- this.$filterElm.val('');
- this.$filterElm.trigger('change');
+ this._filterElm.value = '';
+ this._filterElm.dispatchEvent(new Event('change'));
}
}
@@ -109,14 +111,12 @@ export class InputFilter implements Filter {
* destroy the filter
*/
destroy() {
- if (this.$filterElm) {
- this.$filterElm.off('keyup blur change wheel').remove();
- }
- this.$filterElm = null;
+ this._bindEventService.unbindAll();
+ this._filterElm?.remove?.();
}
- getValue() {
- return this.$filterElm.val();
+ getValue(): string {
+ return this._filterElm.value;
}
/** Set value(s) on the DOM element */
@@ -125,7 +125,7 @@ export class InputFilter implements Filter {
let searchValue: SearchTerm = '';
for (const value of searchValues) {
searchValue = operator ? this.addOptionalOperatorIntoSearchString(value, operator) : value;
- this.$filterElm.val(searchValue);
+ this._filterElm.value = `${searchValue ?? ''}`;
}
// set the operator when defined
@@ -177,64 +177,62 @@ export class InputFilter implements Filter {
return outputValue;
}
- /**
- * Create the HTML template as a string
- */
- protected buildTemplateHtmlString() {
- const columnId = this.columnDef?.id ?? '';
- let placeholder = (this.gridOptions) ? (this.gridOptions.defaultFilterPlaceholder || '') : '';
- if (this.columnFilter && this.columnFilter.placeholder) {
- placeholder = this.columnFilter.placeholder;
- }
- return ``;
- }
-
/**
* From the html template string, create a DOM element
- * @param filterTemplate
+ * @param {Object} searchTerm - filter search term
+ * @returns {Object} DOM element filter
*/
- protected createDomElement(filterTemplate: string, searchTerm?: SearchTerm) {
+ protected createDomElement(searchTerm?: SearchTerm) {
const columnId = this.columnDef?.id ?? '';
- const $headerElm = this.grid.getHeaderRowColumn(columnId);
- $($headerElm).empty();
+ const headerElm = this.grid.getHeaderRowColumn(columnId);
+ emptyElement(headerElm);
// create the DOM element & add an ID and filter class
- const $filterElm = $(filterTemplate);
+ let placeholder = this.gridOptions?.defaultFilterPlaceholder ?? '';
+ if (this.columnFilter?.placeholder) {
+ placeholder = this.columnFilter.placeholder;
+ }
+
+ const inputElm = document.createElement('input');
+ inputElm.type = this._inputType || 'text';
+ inputElm.className = `form-control search-filter filter-${columnId}`;
+ inputElm.autocomplete = 'off';
+ inputElm.placeholder = placeholder;
+ inputElm.setAttribute('role', 'presentation');
- $filterElm.val(searchTerm as string);
- $filterElm.data('columnId', columnId);
+ inputElm.value = (searchTerm ?? '') as string;
+ inputElm.dataset.columnid = `${columnId}`;
// if there's a search term, we will add the "filled" class for styling purposes
if (searchTerm) {
- $filterElm.addClass('filled');
+ inputElm.classList.add('filled');
}
- // append the new DOM element to the header row
- if ($filterElm && typeof $filterElm.appendTo === 'function') {
- $filterElm.appendTo($headerElm);
- }
+ // append the new DOM element to the header row & an empty span
+ headerElm.appendChild(inputElm);
+ headerElm.appendChild(document.createElement('span'));
- return $filterElm;
+ return inputElm;
}
/**
* Event handler to cover the following (keyup, change, mousewheel & spinner)
* We will trigger the Filter Service callback from this handler
*/
- protected handleInputChange(event: KeyboardEvent & { target: any; }) {
+ protected handleInputChange(event: Event) {
if (this._clearFilterTriggered) {
this.callback(event, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery });
- this.$filterElm.removeClass('filled');
+ this._filterElm.classList.remove('filled');
} else {
const eventType = event?.type ?? '';
- let value = event?.target?.value ?? '';
+ let value = (event?.target as HTMLInputElement)?.value ?? '';
const enableWhiteSpaceTrim = this.gridOptions.enableFilterTrimWhiteSpace || this.columnFilter.enableTrimWhiteSpace;
if (typeof value === 'string' && enableWhiteSpaceTrim) {
value = value.trim();
}
- value === '' ? this.$filterElm.removeClass('filled') : this.$filterElm.addClass('filled');
+ value === '' ? this._filterElm.classList.remove('filled') : this._filterElm.classList.add('filled');
const callbackArgs = { columnDef: this.columnDef, operator: this.operator, searchTerms: [value], shouldTriggerQuery: this._shouldTriggerQuery };
- const typingDelay = (eventType === 'keyup' && event?.key !== 'Enter') ? this._debounceTypingDelay : 0;
+ const typingDelay = (eventType === 'keyup' && (event as KeyboardEvent)?.key !== 'Enter') ? this._debounceTypingDelay : 0;
if (typingDelay > 0) {
clearTimeout(this._timer as NodeJS.Timeout);
diff --git a/packages/common/src/filters/inputMaskFilter.ts b/packages/common/src/filters/inputMaskFilter.ts
index 9c20568d5..b4b2644d7 100644
--- a/packages/common/src/filters/inputMaskFilter.ts
+++ b/packages/common/src/filters/inputMaskFilter.ts
@@ -42,47 +42,50 @@ export class InputMaskFilter extends InputFilter {
// filter input can only have 1 search term, so we will use the 1st array index if it exist
const searchTerm = (Array.isArray(this.searchTerms) && this.searchTerms.length >= 0) ? this.searchTerms[0] : '';
- // step 1, create HTML string template
- const filterTemplate = this.buildTemplateHtmlString();
+ // step 1, create the DOM Element of the filter & initialize it if searchTerm is filled
+ this._filterElm = this.createDomElement(searchTerm);
- // step 2, create the DOM Element of the filter & initialize it if searchTerm is filled
- this.$filterElm = this.createDomElement(filterTemplate, searchTerm);
-
- // step 3, subscribe to the keyup blur change event and run the callback when that happens
+ // step 2, subscribe to the input event and run the callback when that happens
// also add/remove "filled" class for styling purposes
+ // we'll use all necessary events to cover the following (keyup, change, mousewheel & spinner)
+ this._bindEventService.bind(this._filterElm, ['keyup', 'blur', 'change'], this.handleInputChange.bind(this));
+ }
- this.$filterElm.on('keyup blur change', (e: any) => {
- let value = '';
- if (e && e.target && e.target.value) {
- let targetValue = e.target.value;
- const enableWhiteSpaceTrim = this.gridOptions.enableFilterTrimWhiteSpace || this.columnFilter.enableTrimWhiteSpace;
- if (typeof targetValue === 'string' && enableWhiteSpaceTrim) {
- targetValue = targetValue.trim();
- }
+ /**
+ * Event handler to cover the following (keyup, change, mousewheel & spinner)
+ * We will trigger the Filter Service callback from this handler
+ */
+ protected handleInputChange(event: Event) {
+ let value = '';
+ if ((event?.target as HTMLInputElement)?.value) {
+ let targetValue = (event?.target as HTMLInputElement)?.value ?? '';
+ const enableWhiteSpaceTrim = this.gridOptions.enableFilterTrimWhiteSpace || this.columnFilter.enableTrimWhiteSpace;
+ if (typeof targetValue === 'string' && enableWhiteSpaceTrim) {
+ targetValue = targetValue.trim();
+ }
- // if it has a mask, we need to do a bit more work
- // and replace the filter string by the masked output without triggering an event
- const unmaskedValue = this.unmaskValue(targetValue);
- const maskedValue = this.maskValue(unmaskedValue);
- value = unmaskedValue;
+ // if it has a mask, we need to do a bit more work
+ // and replace the filter string by the masked output without triggering an event
+ const unmaskedValue = this.unmaskValue(targetValue);
+ const maskedValue = this.maskValue(unmaskedValue);
+ value = unmaskedValue;
- if (e.keyCode >= 48) {
- this.$filterElm.val(maskedValue); // replace filter string with masked string
- e.preventDefault();
- }
+ if ((event as KeyboardEvent)?.keyCode >= 48) {
+ this._filterElm.value = maskedValue; // replace filter string with masked string
+ event.preventDefault();
}
+ }
- if (this._clearFilterTriggered) {
- this.callback(e, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery });
- this.$filterElm.removeClass('filled');
- } else {
- this.$filterElm.addClass('filled');
- this.callback(e, { columnDef: this.columnDef, operator: this.operator, searchTerms: [value], shouldTriggerQuery: this._shouldTriggerQuery });
- }
- // reset both flags for next use
- this._clearFilterTriggered = false;
- this._shouldTriggerQuery = true;
- });
+ if (this._clearFilterTriggered) {
+ this.callback(event, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery });
+ this._filterElm.classList.remove('filled');
+ } else {
+ this._filterElm.classList.add('filled');
+ this.callback(event, { columnDef: this.columnDef, operator: this.operator, searchTerms: [value], shouldTriggerQuery: this._shouldTriggerQuery });
+ }
+ // reset both flags for next use
+ this._clearFilterTriggered = false;
+ this._shouldTriggerQuery = true;
}
/** From a regular string, we will use the mask to output a new string */
diff --git a/packages/common/src/filters/nativeSelectFilter.ts b/packages/common/src/filters/nativeSelectFilter.ts
index 4105b12e2..bfe2c1149 100644
--- a/packages/common/src/filters/nativeSelectFilter.ts
+++ b/packages/common/src/filters/nativeSelectFilter.ts
@@ -72,7 +72,7 @@ export class NativeSelectFilter implements Filter {
// filter input can only have 1 search term, so we will use the 1st array index if it exist
let searchTerm = (Array.isArray(this.searchTerms) && this.searchTerms.length >= 0) ? this.searchTerms[0] : '';
if (typeof searchTerm === 'boolean' || typeof searchTerm === 'number') {
- searchTerm = `${searchTerm}`;
+ searchTerm = `${searchTerm ?? ''}`;
}
// step 1, create HTML string template
diff --git a/packages/common/src/services/__tests__/filter.service.spec.ts b/packages/common/src/services/__tests__/filter.service.spec.ts
index 9def3ec2e..53c011b3a 100644
--- a/packages/common/src/services/__tests__/filter.service.spec.ts
+++ b/packages/common/src/services/__tests__/filter.service.spec.ts
@@ -19,7 +19,7 @@ import {
SlickGrid,
SlickNamespace,
} from '../../interfaces/index';
-import { Filters } from '../../filters';
+import { Filters, InputFilter } from '../../filters';
import { FilterService } from '../filter.service';
import { FilterFactory } from '../../filters/filterFactory';
import { getParsedSearchTermsByFieldType } from '../../filter-conditions';
@@ -133,6 +133,7 @@ describe('FilterService', () => {
const filterFactory = new FilterFactory(slickgridConfig, translateService, collectionService);
service = new FilterService(filterFactory, pubSubServiceStub, sharedService, backendUtilityService, rxjsResourceStub);
slickgridEventHandler = service.eventHandler;
+ jest.spyOn(gridStub, 'getHeaderRowColumn').mockReturnValue(div);
});
afterEach(() => {
@@ -175,7 +176,7 @@ describe('FilterService', () => {
expect(columnFilters).toEqual({});
expect(filterMetadataArray.length).toBe(1);
- expect(filterMetadataArray[0]).toContainEntry(['$filterElm', expect.anything()]);
+ expect(filterMetadataArray[0] instanceof InputFilter).toBeTruthy();
expect(filterMetadataArray[0]).toContainEntry(['searchTerms', []]);
});
@@ -261,7 +262,7 @@ describe('FilterService', () => {
expect(columnFilters).toEqual({});
expect(filterMetadataArray.length).toBe(1);
- expect(filterMetadataArray[0]).toContainEntry(['$filterElm', expect.anything()]);
+ expect(filterMetadataArray[0] instanceof InputFilter).toBeTruthy();
expect(filterMetadataArray[0]).toContainEntry(['searchTerms', []]);
});
@@ -1564,7 +1565,7 @@ describe('FilterService', () => {
expect(spySetSortCols).toHaveBeenCalledWith([{ columnId: 'file', sortAsc: true }]);
expect(columnFilters).toEqual({});
expect(filterMetadataArray.length).toBe(1);
- expect(filterMetadataArray[0]).toContainEntry(['$filterElm', expect.anything()]);
+ expect(filterMetadataArray[0] instanceof InputFilter).toBeTruthy();
expect(filterMetadataArray[0]).toContainEntry(['searchTerms', []]);
});