Skip to content

Commit 84da5f4

Browse files
Samir Hassan Ayoubalinelariguet
authored andcommitted
fix(select): corrigido scroll dos itens para quando houver valor atribuído no ngModel
Revisadas e reordenadas chamadas de métodos para cálculo de altura do scroll. DTHFUI-963
1 parent 00c93b8 commit 84da5f4

File tree

2 files changed

+159
-71
lines changed

2 files changed

+159
-71
lines changed

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

Lines changed: 131 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -56,27 +56,6 @@ describe('PoSelectComponent:', () => {
5656
});
5757
});
5858

59-
it('should not change the selected item with undefined value', () => {
60-
spyOn(component, 'updateModel');
61-
62-
component.onSelectChange(undefined);
63-
expect(component.updateModel).not.toHaveBeenCalled();
64-
});
65-
66-
it('should selected item with value', () => {
67-
spyOn(component, 'updateModel');
68-
69-
component.onSelectChange(component.options[0].value);
70-
expect(component.updateModel).toHaveBeenCalledWith(component.options[0]);
71-
});
72-
73-
it('should not change the selected item with invalid value', () => {
74-
spyOn(component, 'updateModel');
75-
76-
component.onSelectChange(5);
77-
expect(component.updateModel).not.toHaveBeenCalled();
78-
});
79-
8059
it('should hide the dropdown when was click out of the div', done => {
8160
fixture.whenStable().then(() => {
8261
fixture.detectChanges();
@@ -116,19 +95,6 @@ describe('PoSelectComponent:', () => {
11695
expect(fakeThis.updateModel).toHaveBeenCalled();
11796
});
11897

119-
it('should receive the changed value in the model', () => {
120-
component.writeValue(1);
121-
expect(component.options).not.toBeNull();
122-
});
123-
124-
it('should calculate height scroll with heightScrollValue is greater and less values to clientHeight', () => {
125-
spyOn(component, <any>'getSelectItemHeight').and.returnValue(20);
126-
127-
expect(component.scrollValue(10, 60)).toBe(220);
128-
expect(component.scrollValue(1, 60)).toBe(0);
129-
expect(component.scrollValue(0, 60)).toBe(0);
130-
});
131-
13298
it('should click in document', () => {
13399
const documentBody = document.body;
134100
spyOn(documentBody, 'dispatchEvent');
@@ -175,25 +141,6 @@ describe('PoSelectComponent:', () => {
175141
expect(fakeThis.ngModelChange.emit).toHaveBeenCalled();
176142
});
177143

178-
it('should define selectedValue with undefined', () => {
179-
component.writeValue(undefined);
180-
181-
expect(component.selectedValue).toBeUndefined();
182-
});
183-
184-
it('should define selectedValue value with undefined using options empty', () => {
185-
component.selectedValue = 'payment';
186-
component.options.length = 0;
187-
component.writeValue(undefined);
188-
expect(component.selectedValue).toBeUndefined();
189-
});
190-
191-
it('should define selectedValue with undefined when optionsFound is false', () => {
192-
component.selectedValue = 'payment';
193-
component.writeValue('value invalid');
194-
expect(component.selectedValue).toBeUndefined();
195-
});
196-
197144
describe('Properties:', () => {
198145

199146
it('isInvisibleSelectNative: should return `true` if `isMobile` and `readonly` are `true`', () => {
@@ -626,6 +573,137 @@ describe('PoSelectComponent:', () => {
626573
expect(component['setPositionDropdown']).not.toHaveBeenCalled();
627574
});
628575

576+
it('showDropdown: should call `setScrollPosition` if option contains value', () => {
577+
component.readonly = false;
578+
spyOn(component, <any>'setScrollPosition');
579+
580+
component['showDropdown']();
581+
582+
expect(component['setScrollPosition']).toHaveBeenCalled();
583+
});
584+
585+
it('showDropdown: shouldn`t call `setScrollPosition` if option is empty', () => {
586+
component.readonly = false;
587+
component.options.length = 0;
588+
spyOn(component, <any>'setScrollPosition');
589+
590+
component['showDropdown']();
591+
592+
expect(component['setScrollPosition']).not.toHaveBeenCalled();
593+
});
594+
595+
it('onSelectChange: shouldn`t call `updateModel` and `setScrollPosition` if value is undefined', () => {
596+
spyOn(component, 'updateModel');
597+
spyOn(component, <any>'setScrollPosition');
598+
599+
component.onSelectChange(undefined);
600+
expect(component.updateModel).not.toHaveBeenCalled();
601+
expect(component['setScrollPosition']).not.toHaveBeenCalled();
602+
});
603+
604+
it('onSelectChange: should call `updateModel` and `setScrollPosition` if value is valid', () => {
605+
spyOn(component, 'updateModel');
606+
spyOn(component, <any>'setScrollPosition');
607+
608+
component.onSelectChange(component.options[0].value);
609+
expect(component.updateModel).toHaveBeenCalledWith(component.options[0]);
610+
expect(component['setScrollPosition']).toHaveBeenCalledWith(component.options[0].value);
611+
});
612+
613+
it('onSelectChange: shouldn`t call `updateModel` and `setScrollPosition` if value is invalid', () => {
614+
spyOn(component, 'updateModel');
615+
spyOn(component, <any>'setScrollPosition');
616+
617+
component.onSelectChange(5);
618+
expect(component.updateModel).not.toHaveBeenCalled();
619+
expect(component['setScrollPosition']).not.toHaveBeenCalled();
620+
});
621+
622+
it('scrollValue: should return properly values', () => {
623+
spyOn(component, <any>'getSelectItemHeight').and.returnValue(20);
624+
625+
expect(component.scrollValue(10, 60)).toBe(200);
626+
expect(component.scrollValue(1, 60)).toBe(0);
627+
expect(component.scrollValue(0, 60)).toBe(0);
628+
});
629+
630+
it('writeValue: should receive the changed value in the model', () => {
631+
component.writeValue(1);
632+
expect(component.options).not.toBeNull();
633+
});
634+
635+
it('writeValue: should define selectedValue with undefined', () => {
636+
component.writeValue(undefined);
637+
638+
expect(component.selectedValue).toBeUndefined();
639+
});
640+
641+
it('writeValue: should define selectedValue value with undefined if options is empty', () => {
642+
component.selectedValue = 'payment';
643+
component.options.length = 0;
644+
component.writeValue(undefined);
645+
expect(component.selectedValue).toBeUndefined();
646+
});
647+
648+
it('writeValue: should define selectedValue with undefined and doesn`t call setScrollPosition if optionsFound is false', () => {
649+
component.selectedValue = 'payment';
650+
spyOn(component, <any>'setScrollPosition');
651+
652+
component.writeValue('value invalid');
653+
expect(component.selectedValue).toBeUndefined();
654+
expect(component['setScrollPosition']).not.toHaveBeenCalled();
655+
});
656+
657+
it('writeValue: should set property values and call `setScrollPosition` if is a valid option', () => {
658+
spyOn(component, <any>'findOptionValue').and.returnValue(component.options[0]);
659+
spyOn(component, <any>'setScrollPosition');
660+
661+
component.writeValue(component.options[0]);
662+
663+
expect(component.selectedValue).toBe(component.options[0].value);
664+
expect(component.displayValue).toBe(component.options[0].label);
665+
expect(component['setScrollPosition']).toHaveBeenCalledWith(component.options[0].value);
666+
});
667+
668+
it('findOptionValue: should return undefined if it receives an undefined parameter', () => {
669+
const expectedValue = component['findOptionValue'](undefined);
670+
671+
expect(expectedValue).toBeUndefined();
672+
});
673+
674+
it('findOptionValue: should return the properly option if it receives a valid parameter', () => {
675+
const expectedValue = component['findOptionValue'](component.options[0].value);
676+
677+
expect(expectedValue).toEqual(component.options[0]);
678+
});
679+
680+
it('setScrollPosition: should call `scrollValue` if the option has been found', () => {
681+
spyOn(component, <any>'findOptionValue').and.returnValue(component.options[0]);
682+
spyOn(component, <any>'scrollValue');
683+
684+
component['setScrollPosition'](component.options[0].value);
685+
686+
expect(component.scrollValue).toHaveBeenCalledWith(0, 0);
687+
});
688+
689+
it('setScrollPosition: shouldn`t call `scrollValue` if is an undefined option', () => {
690+
spyOn(component, <any>'findOptionValue').and.returnValue(undefined);
691+
spyOn(component, <any>'scrollValue');
692+
693+
component['setScrollPosition'](undefined);
694+
695+
expect(component.scrollValue).not.toHaveBeenCalled();
696+
});
697+
698+
it('setScrollPosition: shouldn`t call `scrollValue` if is an invalid option', () => {
699+
spyOn(component, <any>'findOptionValue').and.returnValue(undefined);
700+
spyOn(component, <any>'scrollValue');
701+
702+
component['setScrollPosition'](component.options[0].value);
703+
704+
expect(component.scrollValue).not.toHaveBeenCalled();
705+
});
706+
629707
});
630708

631709
describe('Templates:', () => {

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

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -156,24 +156,18 @@ export class PoSelectComponent extends PoSelectBaseComponent implements DoCheck
156156
}
157157

158158
onOptionClick(option: PoSelectOption) {
159-
this.toggleButton();
160159
this.updateModel(option);
160+
this.toggleButton();
161161
}
162162

163163
// Altera o valor ao selecionar um item.
164164
onSelectChange(value: any) {
165-
const ulDropdpwn = this.element.nativeElement.querySelector('ul.po-select-content');
166-
167165
if (value && this.options && this.options.length) {
168-
169-
const optionFound: PoSelectOption = this.options.find(option => {
170-
return this.isEqual(option.value, value);
171-
});
166+
const optionFound: PoSelectOption = this.findOptionValue(value);
172167

173168
if (optionFound) {
174-
const index = this.options.indexOf(optionFound);
175-
ulDropdpwn.scrollTop = this.scrollValue(index, ulDropdpwn.clientHeight);
176169
this.updateModel(optionFound);
170+
this.setScrollPosition(optionFound.value);
177171
}
178172
}
179173
}
@@ -185,7 +179,8 @@ export class PoSelectComponent extends PoSelectBaseComponent implements DoCheck
185179
}
186180

187181
scrollValue(index, clientHeight) {
188-
const heightScrollValue: number = (index + 1) * this.getSelectItemHeight();
182+
const heightScrollValue: number = (index) * this.getSelectItemHeight();
183+
189184
return this.scrollPosition = heightScrollValue > clientHeight ? heightScrollValue : 0;
190185
}
191186

@@ -218,15 +213,13 @@ export class PoSelectComponent extends PoSelectBaseComponent implements DoCheck
218213

219214
// Recebe as alterações do model
220215
writeValue(value: any) {
221-
222-
const optionFound = this.options.find(option => {
223-
return this.isEqual(option.value, value);
224-
});
216+
const optionFound: PoSelectOption = this.findOptionValue(value);
225217

226218
if (optionFound) {
227219
this.selectElement.nativeElement.value = optionFound.value;
228220
this.selectedValue = optionFound.value;
229221
this.displayValue = (optionFound.label);
222+
this.setScrollPosition(optionFound.value);
230223

231224
} else if (validValue(this.selectedValue)) {
232225
this.selectElement.nativeElement.value = undefined;
@@ -250,6 +243,10 @@ export class PoSelectComponent extends PoSelectBaseComponent implements DoCheck
250243
});
251244
}
252245

246+
private findOptionValue(value: any) {
247+
return this.options.find(option => this.isEqual(option.value, value));
248+
}
249+
253250
private getSelectItemHeight() {
254251
const selectItem = this.selector('div.po-select-item');
255252

@@ -295,19 +292,32 @@ export class PoSelectComponent extends PoSelectBaseComponent implements DoCheck
295292
this.controlPosition.adjustPosition(poSelectContentPositionDefault);
296293
}
297294

295+
private setScrollPosition(value: any) {
296+
const ulDropdpwn = this.element.nativeElement.querySelector('ul.po-select-content');
297+
298+
if (value && this.options && this.options.length) {
299+
const optionFound: PoSelectOption = this.findOptionValue(value);
300+
301+
if (optionFound) {
302+
const index = this.options.indexOf(optionFound);
303+
ulDropdpwn.scrollTop = this.scrollValue(index, ulDropdpwn.clientHeight);
304+
}
305+
}
306+
}
307+
298308
private showDropdown() {
299309
if (!this.readonly) {
300310
this.selectElement.nativeElement.focus();
301-
if (this.options && this.options.length) {
302-
const ulDropdpwn = this.element.nativeElement.querySelector('ul.po-select-content');
303-
ulDropdpwn.scrollTop = this.scrollPosition;
304-
}
305311
this.selectIcon = 'po-icon-arrow-up';
306312
this.selector('.po-select-container').classList.add('po-select-show');
307313
this.open = true;
308314
this.changeDetector.markForCheck();
309315
this.setPositionDropdown();
310316
this.initializeListeners();
317+
318+
if (this.options && this.options.length) {
319+
this.setScrollPosition(this.selectedValue);
320+
}
311321
}
312322
}
313323

0 commit comments

Comments
 (0)