Skip to content

Commit 6eed13e

Browse files
committed
feat(combo): considera p-remove-initial-filter junto ao p-filter-service
1 parent 69ec268 commit 6eed13e

File tree

8 files changed

+177
-22
lines changed

8 files changed

+177
-22
lines changed

projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search.component.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import {
55
OnDestroy,
66
ChangeDetectorRef,
77
AfterViewInit,
8-
SimpleChanges
8+
SimpleChanges,
9+
OnChanges
910
} from '@angular/core';
1011

1112
import { Observable, Subscription } from 'rxjs';
@@ -53,7 +54,7 @@ type UrlOrPoCustomizationFunction = string | (() => PoPageDynamicSearchOptions);
5354
})
5455
export class PoPageDynamicSearchComponent
5556
extends PoPageDynamicSearchBaseComponent
56-
implements OnInit, OnDestroy, AfterViewInit
57+
implements OnInit, OnDestroy, AfterViewInit, OnChanges
5758
{
5859
@ViewChild(PoAdvancedFilterComponent, { static: true }) poAdvancedFilter: PoAdvancedFilterComponent;
5960
@ViewChild(PoPageListComponent, { static: true }) poPageList: PoPageListComponent;

projects/ui/src/lib/components/po-dynamic/po-dynamic-form/po-dynamic-form-field.interface.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,4 +781,14 @@ export interface PoDynamicFormField extends PoDynamicField {
781781
* **Componente compatível**: `po-upload`
782782
*/
783783
onUpload?: Function;
784+
785+
/**
786+
*
787+
* Define que o filtro no primeiro clique será removido.
788+
*
789+
* > Caso o combo tenha um valor padrão de inicialização, o primeiro clique
790+
* no componente retornará todos os itens da lista e não apenas o item inicialiazado.
791+
*
792+
*/
793+
removeInitialFilter?: boolean;
784794
}

projects/ui/src/lib/components/po-dynamic/po-dynamic-form/po-dynamic-form-fields/po-dynamic-form-fields.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@
275275
[p-disabled-tab-filter]="field.disabledTabFilter"
276276
[p-debounce-time]="field.debounceTime"
277277
[p-change-on-enter]="field.changeOnEnter"
278+
[p-remove-initial-filter]="field.removeInitialFilter"
278279
>
279280
</po-combo>
280281

projects/ui/src/lib/components/po-field/po-combo/po-combo-base.component.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,14 @@ export abstract class PoComboBaseComponent implements ControlValueAccessor, OnIn
909909
if (validValue(value) && !this.service && this.comboOptionsList && this.comboOptionsList.length) {
910910
const option = this.getOptionFromValue(value, this.comboOptionsList);
911911
this.updateSelectedValue(option);
912+
913+
this.comboOptionsList = this.comboOptionsList.map((option: any) => {
914+
if (this.isEqual(option[this.dynamicValue], value)) {
915+
return { ...option, selected: true };
916+
}
917+
return option;
918+
});
919+
912920
this.updateComboList();
913921
this.removeInitialFilter = false;
914922
return;

projects/ui/src/lib/components/po-field/po-combo/po-combo.component.spec.ts

Lines changed: 105 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,24 @@ describe('PoComboComponent:', () => {
171171
expect(fakeThis.applyFilter).toHaveBeenCalled();
172172
});
173173

174+
it('should reset filter and ensure hasNext is true when isFirstFilter and removeInitialFilter are true', () => {
175+
const fakeThis = {
176+
isFirstFilter: true,
177+
removeInitialFilter: true,
178+
selectedValue: true,
179+
defaultService: component.defaultService,
180+
applyFilter: component.applyFilter,
181+
setScrollingControl: component['setScrollingControl']
182+
};
183+
184+
spyOn(fakeThis, 'applyFilter');
185+
spyOn(fakeThis, 'setScrollingControl');
186+
component.applyFilterInFirstClick.call(fakeThis);
187+
188+
expect(component.options).toEqual([]);
189+
expect(fakeThis.defaultService.hasNext).toBeTruthy();
190+
});
191+
174192
it('shouldn`t call applyFilter', () => {
175193
const fakeThis = {
176194
isFirstFilter: true,
@@ -183,6 +201,49 @@ describe('PoComboComponent:', () => {
183201
expect(fakeThis.applyFilter).not.toHaveBeenCalled();
184202
});
185203

204+
it('should update cacheOptions with selected item based on selectedValue', () => {
205+
component.selectedValue = '0448093615904';
206+
207+
(component as any).comboOptionsList = [
208+
{ value: '0448093615903', name: 'Option 1' },
209+
{ value: '0448093615904', name: 'Option 2' },
210+
{ value: '0448093615905', name: 'Option 3' }
211+
];
212+
component.updateCacheOptions();
213+
214+
expect(component.cacheOptions).toEqual([
215+
{ value: '0448093615903', name: 'Option 1' },
216+
{ value: '0448093615904', name: 'Option 2', selected: true },
217+
{ value: '0448093615905', name: 'Option 3' }
218+
]);
219+
});
220+
221+
it('should not update cacheOptions on subsequent calls when isFirstFilter is false', () => {
222+
const items = [...component['comboOptionsList']];
223+
const value = 'Option 3';
224+
225+
component.isFirstFilter = false;
226+
component.cacheOptions = [{ label: 'Option 1', selected: false }];
227+
228+
component.setOptionsByApplyFilter(value, items);
229+
230+
expect(component.cacheOptions).toEqual([{ label: 'Option 1', selected: false }]);
231+
});
232+
233+
it('should call prepareOptions and controlComboVisibility with the correct parameters', () => {
234+
const items = [...component['comboOptionsList']];
235+
const value = 'Option 1';
236+
const reset = true;
237+
238+
spyOn(component as any, 'prepareOptions').and.callThrough();
239+
spyOn(component, 'controlComboVisibility').and.callThrough();
240+
241+
component.setOptionsByApplyFilter(value, items, reset);
242+
243+
expect(component['prepareOptions']).toHaveBeenCalledWith(items);
244+
expect(component.controlComboVisibility).toHaveBeenCalledWith(true, reset);
245+
});
246+
186247
it('should show combo and save the cache', () => {
187248
component.isFirstFilter = true;
188249
component.options = [{ label: '1', value: '1' }];
@@ -1522,37 +1583,64 @@ describe('PoComboComponent - with service:', () => {
15221583
expect(fakeThis.service.getFilteredData).not.toHaveBeenCalled();
15231584
});
15241585

1525-
it('applyFilter: should call PoComboFilterService.getFilteredData() with correct parameters when hasNext is true has page and pageSize', () => {
1586+
it('applyFilter: should set hasNext true if removeInitialFilter is true', () => {
15261587
const fakeThis: any = {
1527-
controlComboVisibility: () => {},
1528-
setOptionsByApplyFilter: () => {},
1588+
removeInitialFilter: true,
1589+
controlComboVisibility: jasmine.createSpy('controlComboVisibility'),
1590+
setOptionsByApplyFilter: jasmine.createSpy('setOptionsByApplyFilter'),
15291591
fieldLabel: 'label',
1530-
filterParams: 'filterParams', // Replace with your filterParams value
1592+
filterParams: 'filterParams',
1593+
isServerSearching: false,
15311594
service: {
1532-
getFilteredData: () => {}
1595+
getFilteredData: jasmine.createSpy('getFilteredData').and.returnValue({
1596+
subscribe: (success: Function, error: Function) => success([])
1597+
})
15331598
},
15341599
defaultService: {
1535-
hasNext: true
1600+
hasNext: false
15361601
},
1537-
infiniteScroll: true,
1538-
page: 1,
1539-
pageSize: 10
1602+
focusItem: jasmine.createSpy('focusItem'),
1603+
onErrorFilteredData: jasmine.createSpy('onErrorFilteredData')
15401604
};
15411605

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

1546-
const expectedParam = {
1547-
property: 'label',
1548-
value: applyFilterValue,
1609+
expect(fakeThis.service.getFilteredData).toHaveBeenCalledWith(
1610+
{ property: 'label', value: applyFilterValue },
1611+
'filterParams'
1612+
);
1613+
});
1614+
1615+
it('applyFilter: Should call the service getFilteredData method with the correct parameters when removeInitialFilter is true and infiniteScroll is enabled.', () => {
1616+
const fakeThis: any = {
1617+
removeInitialFilter: true,
1618+
controlComboVisibility: jasmine.createSpy('controlComboVisibility'),
1619+
setOptionsByApplyFilter: jasmine.createSpy('setOptionsByApplyFilter'),
1620+
infiniteScroll: true,
15491621
page: 1,
1550-
pageSize: 10
1622+
pageSize: 1,
1623+
fieldLabel: 'label',
1624+
filterParams: 'filterParams',
1625+
isServerSearching: false,
1626+
service: {
1627+
getFilteredData: jasmine.createSpy('getFilteredData').and.returnValue({
1628+
subscribe: (success: Function, error: Function) => success([])
1629+
})
1630+
},
1631+
defaultService: {
1632+
hasNext: false
1633+
},
1634+
focusItem: jasmine.createSpy('focusItem'),
1635+
onErrorFilteredData: jasmine.createSpy('onErrorFilteredData')
15511636
};
15521637

1638+
const applyFilterValue = 'applyFilterValue';
1639+
component.applyFilter.apply(fakeThis, [applyFilterValue]);
1640+
15531641
expect(fakeThis.service.getFilteredData).toHaveBeenCalledWith(
1554-
expectedParam,
1555-
'filterParams' // Replace with your filterParams value
1642+
{ property: 'label', value: applyFilterValue, page: 1, pageSize: 1 },
1643+
'filterParams'
15561644
);
15571645
});
15581646

projects/ui/src/lib/components/po-field/po-combo/po-combo.component.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,10 @@ export class PoComboComponent extends PoComboBaseComponent implements AfterViewI
363363
}
364364

365365
applyFilter(value: string, reset: boolean = false, isArrowDown?: boolean) {
366+
if (this.removeInitialFilter) {
367+
this.defaultService.hasNext = true;
368+
}
369+
366370
if (this.defaultService.hasNext) {
367371
this.controlComboVisibility(false, reset);
368372
this.isServerSearching = true;
@@ -397,8 +401,7 @@ export class PoComboComponent extends PoComboBaseComponent implements AfterViewI
397401

398402
if (this.isFirstFilter) {
399403
this.isFirstFilter = !this.isFirstFilter;
400-
401-
this.cacheOptions = this.comboOptionsList;
404+
this.updateCacheOptions();
402405
}
403406
}
404407

@@ -456,7 +459,9 @@ export class PoComboComponent extends PoComboBaseComponent implements AfterViewI
456459
}
457460

458461
applyFilterInFirstClick() {
459-
if (this.isFirstFilter && !this.selectedValue) {
462+
const isEmptyFirstFilter = this.isFirstFilter && !this.selectedValue;
463+
464+
if (this.removeInitialFilter || isEmptyFirstFilter) {
460465
this.options = [];
461466
const scrollingControl = this.setScrollingControl();
462467
this.applyFilter('', scrollingControl);
@@ -583,6 +588,12 @@ export class PoComboComponent extends PoComboBaseComponent implements AfterViewI
583588
this.inputEl.nativeElement.focus();
584589
}
585590

591+
updateCacheOptions(): void {
592+
this.cacheOptions = this.comboOptionsList.map(item =>
593+
item.value === this.selectedValue ? { ...item, selected: true } : item
594+
);
595+
}
596+
586597
private adjustContainerPosition() {
587598
this.controlPosition.adjustPosition(poComboContainerPositionDefault);
588599
}

projects/ui/src/lib/components/po-listbox/po-item-list/po-item-list.component.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,35 @@ describe('PoItemListComponent', () => {
3232
});
3333

3434
describe('Methods:', () => {
35+
describe('shouldUpdateSelected', () => {
36+
it('should return true when searchValue and label from changes exist and have equal values', () => {
37+
const changes = {
38+
searchValue: { currentValue: 'test', previousValue: null, firstChange: true, isFirstChange: () => true },
39+
label: { currentValue: 'test', previousValue: null, firstChange: true, isFirstChange: () => true }
40+
};
41+
component.ngOnChanges(<any>changes);
42+
43+
expect(component['shouldUpdateSelected'](changes)).toBeTrue();
44+
});
45+
46+
it('should return false when searchValue and label from changes exist but have different values', () => {
47+
const changes = {
48+
searchValue: { currentValue: 'test', previousValue: null, firstChange: true, isFirstChange: () => true },
49+
label: { currentValue: 'different', previousValue: null, firstChange: true, isFirstChange: () => true }
50+
};
51+
52+
expect(component['shouldUpdateSelected'](changes)).toBeFalse();
53+
});
54+
55+
it('should return false when searchValue is not present in changes', () => {
56+
const changes = {
57+
label: { currentValue: 'test', previousValue: null, firstChange: true, isFirstChange: () => true }
58+
};
59+
60+
expect(component['shouldUpdateSelected'](changes)).toBeFalse();
61+
});
62+
});
63+
3564
describe('onSelectItem:', () => {
3665
it('should emit tabsItem when tabHide or disabled is changed', () => {
3766
component.isTabs = true;

projects/ui/src/lib/components/po-listbox/po-item-list/po-item-list.component.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,14 @@ export class PoItemListComponent extends PoItemListBaseComponent implements OnCh
2222
super();
2323
}
2424

25+
private shouldUpdateSelected(changes: SimpleChanges): boolean {
26+
return !!(changes.searchValue && changes.label && changes.searchValue.currentValue === changes.label.currentValue);
27+
}
28+
2529
ngOnChanges(changes: SimpleChanges): void {
30+
if (this.shouldUpdateSelected(changes)) {
31+
this.selected = true;
32+
}
2633
if (this.isTabs) {
2734
if (changes.tabHide?.currentValue || changes.disabled?.currentValue) {
2835
this.tabsItem.emit(this.item);

0 commit comments

Comments
 (0)