diff --git a/projects/ui/src/lib/components/po-field/po-input-generic/po-input-generic.spec.ts b/projects/ui/src/lib/components/po-field/po-input-generic/po-input-generic.spec.ts index d7dbcbb9c0..9c29a13596 100644 --- a/projects/ui/src/lib/components/po-field/po-input-generic/po-input-generic.spec.ts +++ b/projects/ui/src/lib/components/po-field/po-input-generic/po-input-generic.spec.ts @@ -55,6 +55,18 @@ describe('PoInputGeneric:', () => { expect(component).toBeTruthy(); }); + it('validateClassesForMask: should called if mask exists', (): void => { + const fakeThis = { + mask: '99999-999', + validateClassesForMask: () => {} + }; + spyOn(fakeThis, 'validateClassesForMask'); + + component.validateInitMask.call(fakeThis); + + expect(fakeThis.validateClassesForMask).toHaveBeenCalled(); + }); + it('should call afterViewInit', () => { spyOn(component, 'afterViewInit'); component.ngAfterViewInit(); @@ -98,10 +110,12 @@ describe('PoInputGeneric:', () => { it('should call keydown from mask with keyCode different 229', () => { const fakeThis = { mask: '(999)', + passedWriteValue: true, objMask: { keydown: (value: any) => {} }, - eventOnBlur: e => {} + eventOnBlur: e => {}, + validateClassesForMask: (value: boolean) => {} }; spyOn(fakeThis.objMask, 'keydown'); component.onKeydown.call(fakeThis, fakeEvent); @@ -111,6 +125,7 @@ describe('PoInputGeneric:', () => { it('should not call keydown from mask with keyCode different 229', () => { const fakeThis = { mask: '', + passedWriteValue: true, objMask: { keydown: (value: any) => {} }, @@ -126,6 +141,7 @@ describe('PoInputGeneric:', () => { it('should not call keydown when the mask is empty and keyCode is different of 229', () => { const fakeThis = { mask: '999', + passedWriteValue: true, objMask: { keydown: (value: any) => {} }, @@ -644,6 +660,55 @@ describe('PoInputGeneric:', () => { expect(component.el.nativeElement.classList).not.toContain('ng-invalid'); }); + it('validateClassesForMask: should add invalid classes if maskValid validation failed.', (): void => { + const fakeThis = { + inputEl: { + nativeElement: { + value: undefined + } + }, + el: { + nativeElement: { + classList: { + add: value => {}, + get: 'ng-invalid-mask' + } + } + }, + mask: '99999-999' + }; + + component.validateClassesForMask.call(fakeThis); + + expect(fakeThis.el.nativeElement.classList.get).toContain('ng-invalid-mask'); + expect(fakeThis.el.nativeElement.classList.get).toContain('ng-invalid-mask'); + }); + + it('validateClassesForMask: should remove invalid classes if maskValid validation sucess.', (): void => { + const fakeThis = { + inputEl: { + nativeElement: { + value: '12345-678' + } + }, + el: { + nativeElement: { + classList: { + add: value => {}, + get: 'ng-invalid-mask', + remove: value => {} + } + } + }, + mask: '99999-999' + }; + spyOn(fakeThis.el.nativeElement.classList, 'remove'); + + component.validateClassesForMask.call(fakeThis); + + expect(fakeThis.el.nativeElement.classList.remove).toHaveBeenCalledWith('ng-invalid-mask'); + }); + it('controlChangeEmitter: should emit change with input value if input value changes', fakeAsync((): void => { const inputValue = 'value'; @@ -690,7 +755,9 @@ describe('PoInputGeneric:', () => { inputEl: '', mask: '', changeModel: component.changeModel, - passedWriteValue: false + passedWriteValue: false, + validateClassesForMask: () => {}, + validateInitMask: () => {} }; spyOn(component.changeModel, 'emit'); component.writeValueModel.call(fakeThis, value); @@ -703,7 +770,8 @@ describe('PoInputGeneric:', () => { inputEl: '', mask: '', changeModel: component.changeModel, - passedWriteValue: false + passedWriteValue: false, + validateClassesForMask: () => {} }; spyOn(component.changeModel, 'emit'); component.writeValueModel.call(fakeThis, ''); @@ -716,7 +784,9 @@ describe('PoInputGeneric:', () => { inputEl: component.inputEl, mask: '', changeModel: component.changeModel, - passedWriteValue: false + passedWriteValue: false, + validateClassesForMask: () => {}, + validateInitMask: () => {} }; component.writeValueModel.call(fakeThis, 'valor'); expect(component.inputEl.nativeElement.value).toBe('valor'); @@ -732,7 +802,9 @@ describe('PoInputGeneric:', () => { _formatModel: false }, changeModel: component.changeModel, - passedWriteValue: false + passedWriteValue: false, + validateClassesForMask: () => {}, + validateInitMask: () => {} }; component.writeValueModel.call(fakeThis, 'valor'); expect(component.inputEl.nativeElement.value).toBe('valor formatted'); @@ -749,7 +821,9 @@ describe('PoInputGeneric:', () => { }, changeModel: component.changeModel, callUpdateModelWithTimeout: component.callUpdateModelWithTimeout, - passedWriteValue: false + passedWriteValue: false, + validateClassesForMask: () => {}, + validateInitMask: () => {} }; const callUpdateModelWithTimeout = spyOn(fakeThis, 'callUpdateModelWithTimeout'); component.writeValueModel.call(fakeThis, 'valor'); diff --git a/projects/ui/src/lib/components/po-field/po-input-generic/po-input-generic.ts b/projects/ui/src/lib/components/po-field/po-input-generic/po-input-generic.ts index 5a84eac6cd..586466f68d 100644 --- a/projects/ui/src/lib/components/po-field/po-input-generic/po-input-generic.ts +++ b/projects/ui/src/lib/components/po-field/po-input-generic/po-input-generic.ts @@ -28,6 +28,9 @@ export abstract class PoInputGeneric extends PoInputBaseComponent implements Aft if (this.mask && !this.readonly && e.target.keyCode !== 229) { this.eventOnBlur(e); this.objMask.keydown(e); + if (this.passedWriteValue) { + this.validateClassesForMask(true); + } } } @@ -166,6 +169,17 @@ export abstract class PoInputGeneric extends PoInputBaseComponent implements Aft } } + validateClassesForMask(keyDown: boolean = false) { + const element = this.el.nativeElement; + const elementValue = this.inputEl.nativeElement.value; + + if (!keyDown && !elementValue) { + element.classList.add('ng-invalid-mask'); + } else { + element.classList.remove('ng-invalid-mask'); + } + } + verifyPattern(pattern: string, value: any) { return new RegExp(pattern).test(value); } @@ -197,6 +211,7 @@ export abstract class PoInputGeneric extends PoInputBaseComponent implements Aft // Emite evento quando o model é atualizado, inclusive a primeira vez if (value) { + this.validateInitMask(); this.changeModel.emit(value); } } @@ -212,5 +227,11 @@ export abstract class PoInputGeneric extends PoInputBaseComponent implements Aft } } + validateInitMask() { + if (this.mask) { + this.validateClassesForMask(); + } + } + abstract extraValidation(c: AbstractControl): { [key: string]: any }; } diff --git a/projects/ui/src/lib/components/po-field/po-input/po-input-base.component.ts b/projects/ui/src/lib/components/po-field/po-input/po-input-base.component.ts index 43bd1cd82f..e1dbd92195 100644 --- a/projects/ui/src/lib/components/po-field/po-input/po-input-base.component.ts +++ b/projects/ui/src/lib/components/po-field/po-input/po-input-base.component.ts @@ -343,7 +343,9 @@ export abstract class PoInputBaseComponent implements ControlValueAccessor, Vali } } - constructor(private cd?: ChangeDetectorRef) {} + constructor(private cd?: ChangeDetectorRef) { + this.objMask = new PoMask(this.mask, this.maskFormatModel); + } callOnChange(value: any) { this.updateModel(value); diff --git a/projects/ui/src/lib/components/po-field/po-input/po-mask.ts b/projects/ui/src/lib/components/po-field/po-input/po-mask.ts index ad5647535c..120f493279 100644 --- a/projects/ui/src/lib/components/po-field/po-input/po-mask.ts +++ b/projects/ui/src/lib/components/po-field/po-input/po-mask.ts @@ -352,8 +352,10 @@ export class PoMask { this.valueToInput = valueProcessed; this.valueToModel = this.removeFormattingValue(valueProcessed); } + return valueProcessed; } + // verifica se tem algum caracter de mascara antes do cursor checkMaskBefore($event: any, position: number) { if (this.isFixedCharacterGuide($event.target.value.toString().charAt(this.initialPosition - 1))) {