diff --git a/projects/ui/src/lib/components/po-dynamic/po-dynamic-form/po-dynamic-form-field.interface.ts b/projects/ui/src/lib/components/po-dynamic/po-dynamic-form/po-dynamic-form-field.interface.ts index 6f61b69a5d..bd470174bb 100644 --- a/projects/ui/src/lib/components/po-dynamic/po-dynamic-form/po-dynamic-form-field.interface.ts +++ b/projects/ui/src/lib/components/po-dynamic/po-dynamic-form/po-dynamic-form-field.interface.ts @@ -720,4 +720,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; } diff --git a/projects/ui/src/lib/components/po-dynamic/po-dynamic-form/po-dynamic-form-fields/po-dynamic-form-fields.component.html b/projects/ui/src/lib/components/po-dynamic/po-dynamic-form/po-dynamic-form-fields/po-dynamic-form-fields.component.html index c3514045a0..5a4e3f1904 100644 --- a/projects/ui/src/lib/components/po-dynamic/po-dynamic-form/po-dynamic-form-fields/po-dynamic-form-fields.component.html +++ b/projects/ui/src/lib/components/po-dynamic/po-dynamic-form/po-dynamic-form-fields/po-dynamic-form-fields.component.html @@ -267,6 +267,7 @@ [p-disabled-tab-filter]="field.disabledTabFilter" [p-debounce-time]="field.debounceTime" [p-change-on-enter]="field.changeOnEnter" + [p-remove-initial-filter]="field.removeInitialFilter" > diff --git a/projects/ui/src/lib/components/po-field/po-combo/po-combo.component.spec.ts b/projects/ui/src/lib/components/po-field/po-combo/po-combo.component.spec.ts index c8d4953cf0..f4c3b8d7ee 100644 --- a/projects/ui/src/lib/components/po-field/po-combo/po-combo.component.spec.ts +++ b/projects/ui/src/lib/components/po-field/po-combo/po-combo.component.spec.ts @@ -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, @@ -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' }]; @@ -1522,40 +1579,73 @@ 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' ); }); + /** + * + * Felipe + * + */ + it('applyFilter: should set isServerSearching and call controlComboVisibility with false if getFilteredData throw error', () => { const value = 'test'; const error = { 'error': { 'message': 'message' } }; diff --git a/projects/ui/src/lib/components/po-field/po-combo/po-combo.component.ts b/projects/ui/src/lib/components/po-field/po-combo/po-combo.component.ts index 49ff698f51..083cddd6b3 100644 --- a/projects/ui/src/lib/components/po-field/po-combo/po-combo.component.ts +++ b/projects/ui/src/lib/components/po-field/po-combo/po-combo.component.ts @@ -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; @@ -397,8 +401,7 @@ export class PoComboComponent extends PoComboBaseComponent implements AfterViewI if (this.isFirstFilter) { this.isFirstFilter = !this.isFirstFilter; - - this.cacheOptions = this.comboOptionsList; + this.updateCacheOptions(); } } @@ -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); @@ -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); }