Skip to content

Commit

Permalink
feat(combo): considera p-remove-initial-filter junto ao p-filter-service
Browse files Browse the repository at this point in the history
  • Loading branch information
felipepetuco committed Jan 21, 2025
1 parent 69ec268 commit c82f888
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
OnDestroy,
ChangeDetectorRef,
AfterViewInit,
SimpleChanges
SimpleChanges,
OnChanges
} from '@angular/core';

import { Observable, Subscription } from 'rxjs';
Expand Down Expand Up @@ -53,7 +54,7 @@ type UrlOrPoCustomizationFunction = string | (() => PoPageDynamicSearchOptions);
})
export class PoPageDynamicSearchComponent
extends PoPageDynamicSearchBaseComponent
implements OnInit, OnDestroy, AfterViewInit
implements OnInit, OnDestroy, AfterViewInit, OnChanges
{
@ViewChild(PoAdvancedFilterComponent, { static: true }) poAdvancedFilter: PoAdvancedFilterComponent;
@ViewChild(PoPageListComponent, { static: true }) poPageList: PoPageListComponent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -781,4 +781,14 @@ export interface PoDynamicFormField extends PoDynamicField {
* **Componente compatível**: `po-upload`
*/
onUpload?: Function;

/**
*
* Define que o filtro no primeiro clique será removido.
*
* > Caso o combo tenha um valor padrão de inicialização, o primeiro clique
* no componente retornará todos os itens da lista e não apenas o item inicialiazado.
*
*/
removeInitialFilter?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@
[p-disabled-tab-filter]="field.disabledTabFilter"
[p-debounce-time]="field.debounceTime"
[p-change-on-enter]="field.changeOnEnter"
[p-remove-initial-filter]="field.removeInitialFilter"
>
</po-combo>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,14 @@ export abstract class PoComboBaseComponent implements ControlValueAccessor, OnIn
if (validValue(value) && !this.service && this.comboOptionsList && this.comboOptionsList.length) {
const option = this.getOptionFromValue(value, this.comboOptionsList);
this.updateSelectedValue(option);

this.comboOptionsList = this.comboOptionsList.map((option: any) => {
if (this.isEqual(option[this.dynamicValue], value)) {
return { ...option, selected: true };
}
return option;
});

this.updateComboList();
this.removeInitialFilter = false;
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,24 @@ describe('PoComboComponent:', () => {
expect(fakeThis.applyFilter).toHaveBeenCalled();
});

it('should reset filter and ensure hasNext is true when isFirstFilter and removeInitialFilter are true', () => {
const fakeThis = {
isFirstFilter: true,
removeInitialFilter: true,
selectedValue: true,
defaultService: component.defaultService,
applyFilter: component.applyFilter,
setScrollingControl: component['setScrollingControl']
};

spyOn(fakeThis, 'applyFilter');
spyOn(fakeThis, 'setScrollingControl');
component.applyFilterInFirstClick.call(fakeThis);

expect(component.options).toEqual([]);
expect(fakeThis.defaultService.hasNext).toBeTruthy();
});

it('shouldn`t call applyFilter', () => {
const fakeThis = {
isFirstFilter: true,
Expand All @@ -183,6 +201,45 @@ describe('PoComboComponent:', () => {
expect(fakeThis.applyFilter).not.toHaveBeenCalled();
});

it('should update cacheOptions with selected item based on getInputValue', () => {
spyOn(component, 'getInputValue').and.returnValue('Option 2');

(component as any).comboOptionsList = [{ label: 'Option 1' }, { label: 'Option 2' }, { label: 'Option 3' }];
component.updateCacheOptions();

expect(component.cacheOptions).toEqual([
{ label: 'Option 1' },
{ label: 'Option 2', selected: true },
{ label: 'Option 3' }
]);
});

it('should not update cacheOptions on subsequent calls when isFirstFilter is false', () => {
const items = [...component['comboOptionsList']];
const value = 'Option 3';

component.isFirstFilter = false;
component.cacheOptions = [{ label: 'Option 1', selected: false }];

component.setOptionsByApplyFilter(value, items);

expect(component.cacheOptions).toEqual([{ label: 'Option 1', selected: false }]);
});

it('should call prepareOptions and controlComboVisibility with the correct parameters', () => {
const items = [...component['comboOptionsList']];
const value = 'Option 1';
const reset = true;

spyOn(component as any, 'prepareOptions').and.callThrough();
spyOn(component, 'controlComboVisibility').and.callThrough();

component.setOptionsByApplyFilter(value, items, reset);

expect(component['prepareOptions']).toHaveBeenCalledWith(items);
expect(component.controlComboVisibility).toHaveBeenCalledWith(true, reset);
});

it('should show combo and save the cache', () => {
component.isFirstFilter = true;
component.options = [{ label: '1', value: '1' }];
Expand Down Expand Up @@ -1522,37 +1579,64 @@ describe('PoComboComponent - with service:', () => {
expect(fakeThis.service.getFilteredData).not.toHaveBeenCalled();
});

it('applyFilter: should call PoComboFilterService.getFilteredData() with correct parameters when hasNext is true has page and pageSize', () => {
it('applyFilter: should set hasNext true if removeInitialFilter is true', () => {
const fakeThis: any = {
controlComboVisibility: () => {},
setOptionsByApplyFilter: () => {},
removeInitialFilter: true,
controlComboVisibility: jasmine.createSpy('controlComboVisibility'),
setOptionsByApplyFilter: jasmine.createSpy('setOptionsByApplyFilter'),
fieldLabel: 'label',
filterParams: 'filterParams', // Replace with your filterParams value
filterParams: 'filterParams',
isServerSearching: false,
service: {
getFilteredData: () => {}
getFilteredData: jasmine.createSpy('getFilteredData').and.returnValue({
subscribe: (success: Function, error: Function) => success([])
})
},
defaultService: {
hasNext: true
hasNext: false
},
infiniteScroll: true,
page: 1,
pageSize: 10
focusItem: jasmine.createSpy('focusItem'),
onErrorFilteredData: jasmine.createSpy('onErrorFilteredData')
};

spyOn(fakeThis.service, 'getFilteredData').and.returnValue(of()); // Using of() to create an empty observable
const applyFilterValue = 'applyFilterValue'; // Replace with your applyFilterValue
const applyFilterValue = 'applyFilterValue';
component.applyFilter.apply(fakeThis, [applyFilterValue]);

const expectedParam = {
property: 'label',
value: applyFilterValue,
expect(fakeThis.service.getFilteredData).toHaveBeenCalledWith(
{ property: 'label', value: applyFilterValue },
'filterParams'
);
});

it('applyFilter: Should call the service getFilteredData method with the correct parameters when removeInitialFilter is true and infiniteScroll is enabled.', () => {
const fakeThis: any = {
removeInitialFilter: true,
controlComboVisibility: jasmine.createSpy('controlComboVisibility'),
setOptionsByApplyFilter: jasmine.createSpy('setOptionsByApplyFilter'),
infiniteScroll: true,
page: 1,
pageSize: 10
pageSize: 1,
fieldLabel: 'label',
filterParams: 'filterParams',
isServerSearching: false,
service: {
getFilteredData: jasmine.createSpy('getFilteredData').and.returnValue({
subscribe: (success: Function, error: Function) => success([])
})
},
defaultService: {
hasNext: false
},
focusItem: jasmine.createSpy('focusItem'),
onErrorFilteredData: jasmine.createSpy('onErrorFilteredData')
};

const applyFilterValue = 'applyFilterValue';
component.applyFilter.apply(fakeThis, [applyFilterValue]);

expect(fakeThis.service.getFilteredData).toHaveBeenCalledWith(
expectedParam,
'filterParams' // Replace with your filterParams value
{ property: 'label', value: applyFilterValue, page: 1, pageSize: 1 },
'filterParams'
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,10 @@ export class PoComboComponent extends PoComboBaseComponent implements AfterViewI
}

applyFilter(value: string, reset: boolean = false, isArrowDown?: boolean) {
if (this.removeInitialFilter) {
this.defaultService.hasNext = true;
}

if (this.defaultService.hasNext) {
this.controlComboVisibility(false, reset);
this.isServerSearching = true;
Expand Down Expand Up @@ -397,8 +401,7 @@ export class PoComboComponent extends PoComboBaseComponent implements AfterViewI

if (this.isFirstFilter) {
this.isFirstFilter = !this.isFirstFilter;

this.cacheOptions = this.comboOptionsList;
this.updateCacheOptions();
}
}

Expand Down Expand Up @@ -456,7 +459,9 @@ export class PoComboComponent extends PoComboBaseComponent implements AfterViewI
}

applyFilterInFirstClick() {
if (this.isFirstFilter && !this.selectedValue) {
const isEmptyFirstFilter = this.isFirstFilter && !this.selectedValue;

if (this.removeInitialFilter || isEmptyFirstFilter) {
this.options = [];
const scrollingControl = this.setScrollingControl();
this.applyFilter('', scrollingControl);
Expand Down Expand Up @@ -583,6 +588,12 @@ export class PoComboComponent extends PoComboBaseComponent implements AfterViewI
this.inputEl.nativeElement.focus();
}

updateCacheOptions(): void {
this.cacheOptions = this.comboOptionsList.map(item =>
item.label === this.getInputValue() ? { ...item, selected: true } : item
);
}

private adjustContainerPosition() {
this.controlPosition.adjustPosition(poComboContainerPositionDefault);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,35 @@ describe('PoItemListComponent', () => {
});

describe('Methods:', () => {
describe('shouldUpdateSelected', () => {
it('should return true when searchValue and label from changes exist and have equal values', () => {
const changes = {
searchValue: { currentValue: 'test', previousValue: null, firstChange: true, isFirstChange: () => true },
label: { currentValue: 'test', previousValue: null, firstChange: true, isFirstChange: () => true }
};
component.ngOnChanges(<any>changes);

expect(component['shouldUpdateSelected'](changes)).toBeTrue();
});

it('should return false when searchValue and label from changes exist but have different values', () => {
const changes = {
searchValue: { currentValue: 'test', previousValue: null, firstChange: true, isFirstChange: () => true },
label: { currentValue: 'different', previousValue: null, firstChange: true, isFirstChange: () => true }
};

expect(component['shouldUpdateSelected'](changes)).toBeFalse();
});

it('should return false when searchValue is not present in changes', () => {
const changes = {
label: { currentValue: 'test', previousValue: null, firstChange: true, isFirstChange: () => true }
};

expect(component['shouldUpdateSelected'](changes)).toBeFalse();
});
});

describe('onSelectItem:', () => {
it('should emit tabsItem when tabHide or disabled is changed', () => {
component.isTabs = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,14 @@ export class PoItemListComponent extends PoItemListBaseComponent implements OnCh
super();
}

private shouldUpdateSelected(changes: SimpleChanges): boolean {
return !!(changes.searchValue && changes.label && changes.searchValue.currentValue === changes.label.currentValue);
}

ngOnChanges(changes: SimpleChanges): void {
if (this.shouldUpdateSelected(changes)) {
this.selected = true;
}
if (this.isTabs) {
if (changes.tabHide?.currentValue || changes.disabled?.currentValue) {
this.tabsItem.emit(this.item);
Expand Down

0 comments on commit c82f888

Please sign in to comment.