Skip to content

Commit

Permalink
chore(filters): align input filters before merging them (#808)
Browse files Browse the repository at this point in the history
* chore(filters): align input filters before merging filters
  • Loading branch information
ghiscoding authored Nov 11, 2022
1 parent 32ff941 commit fe9d71f
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ describe('CompoundInputFilter', () => {
filter.init(filterArguments);
const filterInputElm = divContainer.querySelector('.search-filter.filter-duration input') as HTMLInputElement;

expect(filterInputElm.getAttribute('aria-label')).toBe('Duration Search Filter');
expect(filterInputElm.ariaLabel).toBe('Duration Search Filter');
});

it('should have a placeholder when defined in its column definition', () => {
Expand All @@ -83,7 +83,7 @@ describe('CompoundInputFilter', () => {
const filterInputElm = divContainer.querySelector('.search-filter.filter-duration input') as HTMLInputElement;

expect(filterInputElm.placeholder).toBe(testValue);
expect(filterInputElm.getAttribute('aria-label')).toBe('Duration Search Filter');
expect(filterInputElm.ariaLabel).toBe('Duration Search Filter');
});

it('should call "setValues" and expect that value to be in the callback when triggered', () => {
Expand Down Expand Up @@ -372,7 +372,7 @@ describe('CompoundInputFilter', () => {
it('should have custom compound operator list showing up in the operator select dropdown options list', () => {
mockColumn.outputType = null as any;
filterArguments.searchTerms = ['xyz'];
mockColumn.filter.compoundOperatorList = [
mockColumn.filter!.compoundOperatorList = [
{ operator: '', description: '' },
{ operator: '=', description: 'Equal to' },
{ operator: '<', description: 'Less than' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe('CompoundInputNumberFilter', () => {
filter.init(filterArguments);
const filterInputElm = divContainer.querySelector('.search-filter.filter-duration input') as HTMLInputElement;

expect(filterInputElm.getAttribute('aria-label')).toBe('Duration Search Filter');
expect(filterInputElm.ariaLabel).toBe('Duration Search Filter');
});

it('should initialize the filter and expect an input of type number', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe('CompoundInputPasswordFilter', () => {
filter.init(filterArguments);
const filterInputElm = divContainer.querySelector('.search-filter.filter-duration input') as HTMLInputElement;

expect(filterInputElm.getAttribute('aria-label')).toBe('Duration Search Filter');
expect(filterInputElm.ariaLabel).toBe('Duration Search Filter');
});

it('should initialize the filter and expect an input of type password', () => {
Expand Down
6 changes: 3 additions & 3 deletions packages/common/src/filters/__tests__/inputFilter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe('InputFilter', () => {
filter.init(filterArguments);
const filterInputElm = divContainer.querySelector('input.filter-duration') as HTMLInputElement;

expect(filterInputElm.getAttribute('aria-label')).toBe('Duration Search Filter');
expect(filterInputElm.ariaLabel).toBe('Duration Search Filter');
});

it('should have a placeholder when defined in its column definition', () => {
Expand Down Expand Up @@ -281,7 +281,7 @@ describe('InputFilter', () => {

expect(filterElm.value).toBe('');
expect(filterFilledElms.length).toBe(0);
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: true });
expect(spyCallback).toHaveBeenCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: true });
});

it('should trigger a callback with the clear filter but without querying when when calling the "clear" method with False as argument', () => {
Expand All @@ -295,6 +295,6 @@ describe('InputFilter', () => {

expect(filterElm.value).toBe('');
expect(filterFilledElms.length).toBe(0);
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false });
expect(spyCallback).toHaveBeenCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false });
});
});
6 changes: 3 additions & 3 deletions packages/common/src/filters/__tests__/inputMaskFilter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ describe('InputMaskFilter', () => {
filter.init(filterArguments);
const filterInputElm = divContainer.querySelector('input.filter-mask') as HTMLInputElement;

expect(filterInputElm.getAttribute('aria-label')).toBe('Mask Search Filter');
expect(filterInputElm.ariaLabel).toBe('Mask Search Filter');
});

it('should initialize the filter and define the mask in the column definition instead and get the same output', () => {
Expand Down Expand Up @@ -232,7 +232,7 @@ describe('InputMaskFilter', () => {
const filterElm = divContainer.querySelector('input.filter-mask') as HTMLInputElement;

expect(filterElm.value).toBe('');
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: true });
expect(spyCallback).toHaveBeenCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: true });
});

it('should trigger a callback with the clear filter but without querying when when calling the "clear" method with False as argument', () => {
Expand All @@ -245,6 +245,6 @@ describe('InputMaskFilter', () => {
const filterElm = divContainer.querySelector('input.filter-mask') as HTMLInputElement;

expect(filterElm.value).toBe('');
expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false });
expect(spyCallback).toHaveBeenCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false });
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe('InputNumberFilter', () => {
filter.init(filterArguments);
const filterInputElm = divContainer.querySelector('input.filter-number') as HTMLInputElement;

expect(filterInputElm.getAttribute('aria-label')).toBe('Number Search Filter');
expect(filterInputElm.ariaLabel).toBe('Number Search Filter');
});

it('should initialize the filter and expect an input of type number', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe('InputPasswordFilter', () => {
filter.init(filterArguments);
const filterInputElm = divContainer.querySelector('input.filter-passwordField') as HTMLInputElement;

expect(filterInputElm.getAttribute('aria-label')).toBe('Password Field Search Filter');
expect(filterInputElm.ariaLabel).toBe('Password Field Search Filter');
});

it('should initialize the filter and expect an input of type password', () => {
Expand Down
62 changes: 26 additions & 36 deletions packages/common/src/filters/compoundInputFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ import { TranslaterService } from '../services/translater.service';

export class CompoundInputFilter implements Filter {
protected _bindEventService: BindingEventService;
protected _clearFilterTriggered = false;
protected _currentValue?: number | string;
protected _debounceTypingDelay = 0;
protected _shouldTriggerQuery = true;
protected _inputType = 'text';
protected _timer?: NodeJS.Timeout;
protected _filterElm!: HTMLDivElement;
protected _filterInputElm!: HTMLInputElement;
protected _selectOperatorElm!: HTMLSelectElement;
Expand All @@ -32,18 +32,12 @@ export class CompoundInputFilter implements Filter {
searchTerms: SearchTerm[] = [];
columnDef!: Column;
callback!: FilterCallback;
timer?: NodeJS.Timeout;
filterContainerElm!: HTMLDivElement;

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?.getOptions?.() ?? {};
}

/** Getter for the Column Filter */
get columnFilter(): ColumnFilter {
return this.columnDef?.filter ?? {};
Expand Down Expand Up @@ -74,6 +68,11 @@ export class CompoundInputFilter implements Filter {
this._operator = op;
}

/** Getter for the Grid Options pulled through the Grid Object */
protected get gridOptions(): GridOption {
return this.grid?.getOptions?.() ?? {};
}

/**
* Initialize the Filter
*/
Expand All @@ -99,7 +98,7 @@ 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.createDomFilterElement(searchTerm);

// step 3, subscribe to the keyup event and run the callback when that happens
// also add/remove "filled" class for styling purposes
Expand All @@ -113,15 +112,14 @@ export class CompoundInputFilter implements Filter {
*/
clear(shouldTriggerQuery = true) {
if (this._filterElm && this._selectOperatorElm) {
this._clearFilterTriggered = true;
this._shouldTriggerQuery = shouldTriggerQuery;
this.searchTerms = [];
this._selectOperatorElm.selectedIndex = 0;
this._filterInputElm.value = '';
this._selectOperatorElm.selectedIndex = 0;
this._currentValue = undefined;
this.onTriggerEvent(undefined);
this._filterElm.classList.remove('filled');
this._filterInputElm.classList.remove('filled');
this.onTriggerEvent(undefined, true);
}
}

Expand Down Expand Up @@ -168,7 +166,7 @@ export class CompoundInputFilter implements Filter {
// protected functions
// ------------------

protected buildInputElement(): HTMLInputElement {
protected buildInputElement(searchTerm?: SearchTerm): HTMLInputElement {
const columnId = this.columnDef?.id ?? '';

// create the DOM element & add an ID and filter class
Expand All @@ -177,12 +175,19 @@ export class CompoundInputFilter implements Filter {
placeholder = this.columnFilter.placeholder;
}

const searchVal = `${searchTerm ?? ''}`;
const inputElm = createDomElement('input', {
type: this._inputType || 'text',
autocomplete: 'none', placeholder,
ariaLabel: this.columnFilter?.ariaLabel ?? `${toSentenceCase(columnId + '')} Search Filter`,
className: `form-control compound-input filter-${columnId}`,
value: searchVal,
dataset: { columnid: `${columnId}` }
});
inputElm.setAttribute('aria-label', this.columnFilter?.ariaLabel ?? `${toSentenceCase(columnId + '')} Search Filter`);

if (searchTerm !== undefined) {
this._currentValue = searchVal;
}

return inputElm;
}
Expand Down Expand Up @@ -214,27 +219,20 @@ export class CompoundInputFilter implements Filter {
/**
* Create the DOM element
*/
protected createDomElement(searchTerm?: SearchTerm) {
protected createDomFilterElement(searchTerm?: SearchTerm) {
const columnId = this.columnDef?.id ?? '';
emptyElement(this.filterContainerElm);

// create the DOM Select dropdown for the Operator
this._selectOperatorElm = buildSelectOperator(this.getOperatorOptionValues(), this.gridOptions);
this._filterInputElm = this.buildInputElement();
this._filterInputElm = this.buildInputElement(searchTerm);
const emptySpanElm = createDomElement('span');

const filterContainerElm = createDomElement('div', { className: `form-group search-filter filter-${columnId}` });
const containerInputGroupElm = createDomElement('div', { className: 'input-group' });
const operatorInputGroupAddonElm = createDomElement('div', { className: 'input-group-addon input-group-prepend operator' });

/* the DOM element final structure will be
<div class="input-group">
<div class="input-group-addon input-group-prepend operator">
<select class="form-control"></select>
</div>
<input class="form-control compound-input" type="text" />
</div>
*/
// append operator & input DOM element
operatorInputGroupAddonElm.appendChild(this._selectOperatorElm);
containerInputGroupElm.appendChild(operatorInputGroupAddonElm);
containerInputGroupElm.appendChild(this._filterInputElm);
Expand All @@ -243,13 +241,6 @@ export class CompoundInputFilter implements Filter {
// create the DOM element & add an ID and filter class
filterContainerElm.appendChild(containerInputGroupElm);

this._filterInputElm.dataset.columnid = `${columnId}`;
const searchVal = `${searchTerm ?? ''}`;
this._filterInputElm.value = searchVal;
if (searchTerm !== undefined) {
this._currentValue = searchVal;
}

if (this.operator) {
const operatorShorthand = mapOperatorToShorthandDesignation(this.operator);
this._selectOperatorElm.value = operatorShorthand;
Expand All @@ -272,9 +263,9 @@ export class CompoundInputFilter implements Filter {
* 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: MouseEvent | KeyboardEvent | undefined) {
if (this._clearFilterTriggered) {
this.callback(event, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery });
protected onTriggerEvent(event: MouseEvent | KeyboardEvent | undefined, isClearFilterEvent = false) {
if (isClearFilterEvent) {
this.callback(event, { columnDef: this.columnDef, clearFilterTriggered: isClearFilterEvent, shouldTriggerQuery: this._shouldTriggerQuery });
this._filterElm.classList.remove('filled');
} else {
const eventType = event?.type ?? '';
Expand All @@ -298,16 +289,15 @@ export class CompoundInputFilter implements Filter {
const skipCompoundOperatorFilterWithNullInput = this.columnFilter.skipCompoundOperatorFilterWithNullInput ?? this.gridOptions.skipCompoundOperatorFilterWithNullInput;
if (!skipCompoundOperatorFilterWithNullInput || this._currentValue !== undefined) {
if (typingDelay > 0) {
clearTimeout(this.timer as NodeJS.Timeout);
this.timer = setTimeout(() => this.callback(event, callbackArgs), typingDelay);
clearTimeout(this._timer as NodeJS.Timeout);
this._timer = setTimeout(() => this.callback(event, callbackArgs), typingDelay);
} else {
this.callback(event, callbackArgs);
}
}
}

// reset both flags for next use
this._clearFilterTriggered = false;
this._shouldTriggerQuery = true;
}
}
Loading

0 comments on commit fe9d71f

Please sign in to comment.