Skip to content

Commit 90e9362

Browse files
anlibenrafaellmarques
authored andcommitted
fix(input): adiciona indicação visual de campo inválido
adiciona indicação visual de campo inválido no `po-input` Fixes 7479
1 parent 6c8a9af commit 90e9362

File tree

4 files changed

+106
-7
lines changed

4 files changed

+106
-7
lines changed

projects/ui/src/lib/components/po-field/po-input-generic/po-input-generic.spec.ts

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ describe('PoInputGeneric:', () => {
5555
expect(component).toBeTruthy();
5656
});
5757

58+
it('validateClassesForMask: should called if mask exists', (): void => {
59+
const fakeThis = {
60+
mask: '99999-999',
61+
validateClassesForMask: () => {}
62+
};
63+
spyOn(fakeThis, 'validateClassesForMask');
64+
65+
component.validateInitMask.call(fakeThis);
66+
67+
expect(fakeThis.validateClassesForMask).toHaveBeenCalled();
68+
});
69+
5870
it('should call afterViewInit', () => {
5971
spyOn(component, 'afterViewInit');
6072
component.ngAfterViewInit();
@@ -98,10 +110,12 @@ describe('PoInputGeneric:', () => {
98110
it('should call keydown from mask with keyCode different 229', () => {
99111
const fakeThis = {
100112
mask: '(999)',
113+
passedWriteValue: true,
101114
objMask: {
102115
keydown: (value: any) => {}
103116
},
104-
eventOnBlur: e => {}
117+
eventOnBlur: e => {},
118+
validateClassesForMask: (value: boolean) => {}
105119
};
106120
spyOn(fakeThis.objMask, 'keydown');
107121
component.onKeydown.call(fakeThis, fakeEvent);
@@ -111,6 +125,7 @@ describe('PoInputGeneric:', () => {
111125
it('should not call keydown from mask with keyCode different 229', () => {
112126
const fakeThis = {
113127
mask: '',
128+
passedWriteValue: true,
114129
objMask: {
115130
keydown: (value: any) => {}
116131
},
@@ -126,6 +141,7 @@ describe('PoInputGeneric:', () => {
126141
it('should not call keydown when the mask is empty and keyCode is different of 229', () => {
127142
const fakeThis = {
128143
mask: '999',
144+
passedWriteValue: true,
129145
objMask: {
130146
keydown: (value: any) => {}
131147
},
@@ -644,6 +660,55 @@ describe('PoInputGeneric:', () => {
644660
expect(component.el.nativeElement.classList).not.toContain('ng-invalid');
645661
});
646662

663+
it('validateClassesForMask: should add invalid classes if maskValid validation failed.', (): void => {
664+
const fakeThis = {
665+
inputEl: {
666+
nativeElement: {
667+
value: undefined
668+
}
669+
},
670+
el: {
671+
nativeElement: {
672+
classList: {
673+
add: value => {},
674+
get: 'ng-invalid-mask'
675+
}
676+
}
677+
},
678+
mask: '99999-999'
679+
};
680+
681+
component.validateClassesForMask.call(fakeThis);
682+
683+
expect(fakeThis.el.nativeElement.classList.get).toContain('ng-invalid-mask');
684+
expect(fakeThis.el.nativeElement.classList.get).toContain('ng-invalid-mask');
685+
});
686+
687+
it('validateClassesForMask: should remove invalid classes if maskValid validation sucess.', (): void => {
688+
const fakeThis = {
689+
inputEl: {
690+
nativeElement: {
691+
value: '12345-678'
692+
}
693+
},
694+
el: {
695+
nativeElement: {
696+
classList: {
697+
add: value => {},
698+
get: 'ng-invalid-mask',
699+
remove: value => {}
700+
}
701+
}
702+
},
703+
mask: '99999-999'
704+
};
705+
spyOn(fakeThis.el.nativeElement.classList, 'remove');
706+
707+
component.validateClassesForMask.call(fakeThis);
708+
709+
expect(fakeThis.el.nativeElement.classList.remove).toHaveBeenCalledWith('ng-invalid-mask');
710+
});
711+
647712
it('controlChangeEmitter: should emit change with input value if input value changes', fakeAsync((): void => {
648713
const inputValue = 'value';
649714

@@ -690,7 +755,9 @@ describe('PoInputGeneric:', () => {
690755
inputEl: '',
691756
mask: '',
692757
changeModel: component.changeModel,
693-
passedWriteValue: false
758+
passedWriteValue: false,
759+
validateClassesForMask: () => {},
760+
validateInitMask: () => {}
694761
};
695762
spyOn(component.changeModel, 'emit');
696763
component.writeValueModel.call(fakeThis, value);
@@ -703,7 +770,8 @@ describe('PoInputGeneric:', () => {
703770
inputEl: '',
704771
mask: '',
705772
changeModel: component.changeModel,
706-
passedWriteValue: false
773+
passedWriteValue: false,
774+
validateClassesForMask: () => {}
707775
};
708776
spyOn(component.changeModel, 'emit');
709777
component.writeValueModel.call(fakeThis, '');
@@ -716,7 +784,9 @@ describe('PoInputGeneric:', () => {
716784
inputEl: component.inputEl,
717785
mask: '',
718786
changeModel: component.changeModel,
719-
passedWriteValue: false
787+
passedWriteValue: false,
788+
validateClassesForMask: () => {},
789+
validateInitMask: () => {}
720790
};
721791
component.writeValueModel.call(fakeThis, 'valor');
722792
expect(component.inputEl.nativeElement.value).toBe('valor');
@@ -732,7 +802,9 @@ describe('PoInputGeneric:', () => {
732802
_formatModel: false
733803
},
734804
changeModel: component.changeModel,
735-
passedWriteValue: false
805+
passedWriteValue: false,
806+
validateClassesForMask: () => {},
807+
validateInitMask: () => {}
736808
};
737809
component.writeValueModel.call(fakeThis, 'valor');
738810
expect(component.inputEl.nativeElement.value).toBe('valor formatted');
@@ -749,7 +821,9 @@ describe('PoInputGeneric:', () => {
749821
},
750822
changeModel: component.changeModel,
751823
callUpdateModelWithTimeout: component.callUpdateModelWithTimeout,
752-
passedWriteValue: false
824+
passedWriteValue: false,
825+
validateClassesForMask: () => {},
826+
validateInitMask: () => {}
753827
};
754828
const callUpdateModelWithTimeout = spyOn(fakeThis, <any>'callUpdateModelWithTimeout');
755829
component.writeValueModel.call(fakeThis, 'valor');

projects/ui/src/lib/components/po-field/po-input-generic/po-input-generic.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ export abstract class PoInputGeneric extends PoInputBaseComponent implements Aft
2828
if (this.mask && !this.readonly && e.target.keyCode !== 229) {
2929
this.eventOnBlur(e);
3030
this.objMask.keydown(e);
31+
if (this.passedWriteValue) {
32+
this.validateClassesForMask(true);
33+
}
3134
}
3235
}
3336

@@ -166,6 +169,17 @@ export abstract class PoInputGeneric extends PoInputBaseComponent implements Aft
166169
}
167170
}
168171

172+
validateClassesForMask(keyDown: boolean = false) {
173+
const element = this.el.nativeElement;
174+
const elementValue = this.inputEl.nativeElement.value;
175+
176+
if (!keyDown && !elementValue) {
177+
element.classList.add('ng-invalid-mask');
178+
} else {
179+
element.classList.remove('ng-invalid-mask');
180+
}
181+
}
182+
169183
verifyPattern(pattern: string, value: any) {
170184
return new RegExp(pattern).test(value);
171185
}
@@ -197,6 +211,7 @@ export abstract class PoInputGeneric extends PoInputBaseComponent implements Aft
197211

198212
// Emite evento quando o model é atualizado, inclusive a primeira vez
199213
if (value) {
214+
this.validateInitMask();
200215
this.changeModel.emit(value);
201216
}
202217
}
@@ -212,5 +227,11 @@ export abstract class PoInputGeneric extends PoInputBaseComponent implements Aft
212227
}
213228
}
214229

230+
validateInitMask() {
231+
if (this.mask) {
232+
this.validateClassesForMask();
233+
}
234+
}
235+
215236
abstract extraValidation(c: AbstractControl): { [key: string]: any };
216237
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,9 @@ export abstract class PoInputBaseComponent implements ControlValueAccessor, Vali
343343
}
344344
}
345345

346-
constructor(private cd?: ChangeDetectorRef) {}
346+
constructor(private cd?: ChangeDetectorRef) {
347+
this.objMask = new PoMask(this.mask, this.maskFormatModel);
348+
}
347349

348350
callOnChange(value: any) {
349351
this.updateModel(value);

projects/ui/src/lib/components/po-field/po-input/po-mask.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,8 +352,10 @@ export class PoMask {
352352
this.valueToInput = valueProcessed;
353353
this.valueToModel = this.removeFormattingValue(valueProcessed);
354354
}
355+
355356
return valueProcessed;
356357
}
358+
357359
// verifica se tem algum caracter de mascara antes do cursor
358360
checkMaskBefore($event: any, position: number) {
359361
if (this.isFixedCharacterGuide($event.target.value.toString().charAt(this.initialPosition - 1))) {

0 commit comments

Comments
 (0)