From 997c488cfc9523eaffb164ab02af867ef226cf77 Mon Sep 17 00:00:00 2001 From: andriikamaldinov1 Date: Tue, 4 Jul 2023 11:45:18 +0300 Subject: [PATCH] fix(#1186): fix 1186 --- CHANGELOG.md | 7 ++ projects/ngx-mask-lib/package.json | 2 +- .../src/lib/ngx-mask-applier.service.ts | 1 - .../src/lib/ngx-mask.directive.ts | 8 +- .../ngx-mask-lib/src/lib/ngx-mask.service.ts | 74 +++++++++++++------ .../ngx-mask-lib/src/test/secure-mask.spec.ts | 23 +++++- .../ngx-mask-lib/src/test/separator.spec.ts | 28 +++++++ 7 files changed, 114 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aaede126..b29a257a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 16.2.2(2023-07-03) + +### Fix + +- Fix ([#1186](https://github.com/JsDaddy/ngx-mask/issues/1186)) +- Fix ([#1182](https://github.com/JsDaddy/ngx-mask/issues/1182)) + # 16.2.1(2023-06-30) ### Fix diff --git a/projects/ngx-mask-lib/package.json b/projects/ngx-mask-lib/package.json index 682c16ca..00b05368 100644 --- a/projects/ngx-mask-lib/package.json +++ b/projects/ngx-mask-lib/package.json @@ -1,6 +1,6 @@ { "name": "ngx-mask", - "version": "16.2.1", + "version": "16.2.2", "description": "awesome ngx mask", "keywords": [ "ng2-mask", diff --git a/projects/ngx-mask-lib/src/lib/ngx-mask-applier.service.ts b/projects/ngx-mask-lib/src/lib/ngx-mask-applier.service.ts index d8aa22b7..ddb28fda 100644 --- a/projects/ngx-mask-lib/src/lib/ngx-mask-applier.service.ts +++ b/projects/ngx-mask-lib/src/lib/ngx-mask-applier.service.ts @@ -98,7 +98,6 @@ export class NgxMaskApplierService { // eslint-disable-next-line no-param-reassign inputValue = ''; } - const inputArray: string[] = inputValue.toString().split(MaskExpression.EMPTY_STRING); if ( this.allowNegativeNumbers && diff --git a/projects/ngx-mask-lib/src/lib/ngx-mask.directive.ts b/projects/ngx-mask-lib/src/lib/ngx-mask.directive.ts index 130e1b3e..202fff37 100644 --- a/projects/ngx-mask-lib/src/lib/ngx-mask.directive.ts +++ b/projects/ngx-mask-lib/src/lib/ngx-mask.directive.ts @@ -426,10 +426,10 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida this._position = this._position === 1 && this._inputValue.length === 1 ? null : this._position; - let positionToApply: number = this._position ? this._inputValue.length + position + caretShift : position + (this._code === 'Backspace' && !backspaceShift ? 0 : caretShift); + if (positionToApply > this._getActualInputLength()) { positionToApply = this._getActualInputLength(); } @@ -670,6 +670,12 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida .toString() .replace(MaskExpression.DOT, MaskExpression.COMMA); } + if (this.maskExpression?.startsWith(MaskExpression.SEPARATOR) && this.leadZero) { + this._maskService.applyMask( + inputValue.toString(), + this._maskService.maskExpression + ); + } this._maskService.isNumberValue = true; } diff --git a/projects/ngx-mask-lib/src/lib/ngx-mask.service.ts b/projects/ngx-mask-lib/src/lib/ngx-mask.service.ts index 2a381ca6..843f7403 100644 --- a/projects/ngx-mask-lib/src/lib/ngx-mask.service.ts +++ b/projects/ngx-mask-lib/src/lib/ngx-mask.service.ts @@ -1,9 +1,9 @@ -import { ElementRef, inject, Injectable, Renderer2 } from '@angular/core'; -import { DOCUMENT } from '@angular/common'; +import {ElementRef, inject, Injectable, Renderer2} from '@angular/core'; +import {DOCUMENT} from '@angular/common'; -import { NGX_MASK_CONFIG, IConfig } from './ngx-mask.config'; -import { NgxMaskApplierService } from './ngx-mask-applier.service'; -import { MaskExpression } from './ngx-mask-expression.enum'; +import {NGX_MASK_CONFIG, IConfig} from './ngx-mask.config'; +import {NgxMaskApplierService} from './ngx-mask-applier.service'; +import {MaskExpression} from './ngx-mask-expression.enum'; @Injectable() export class NgxMaskService extends NgxMaskApplierService { @@ -30,15 +30,16 @@ export class NgxMaskService extends NgxMaskApplierService { private _end!: number; // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-explicit-any - public onChange = (_: any) => {}; + public onChange = (_: any) => { + }; private readonly document = inject(DOCUMENT); protected override _config = inject(NGX_MASK_CONFIG); - private readonly _elementRef = inject(ElementRef, { optional: true }); + private readonly _elementRef = inject(ElementRef, {optional: true}); - private readonly _renderer = inject(Renderer2, { optional: true }); + private readonly _renderer = inject(Renderer2, {optional: true}); // eslint-disable-next-line complexity public override applyMask( @@ -48,7 +49,8 @@ export class NgxMaskService extends NgxMaskApplierService { justPasted = false, backspaced = false, // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-explicit-any - cb: (...args: any[]) => any = () => {} + cb: (...args: any[]) => any = () => { + } ): string { if (!maskExpression) { return inputValue !== this.actualValue ? this.actualValue : inputValue; @@ -84,10 +86,10 @@ export class NgxMaskService extends NgxMaskApplierService { ? inputValue.length > actualResult.length ? actualResult.splice(this.selStart, 0, getSymbol) : inputValue.length < actualResult.length - ? actualResult.length - inputValue.length === 1 - ? actualResult.splice(this.selStart - 1, 1) - : actualResult.splice(this.selStart, this.selEnd - this.selStart) - : null + ? actualResult.length - inputValue.length === 1 + ? actualResult.splice(this.selStart - 1, 1) + : actualResult.splice(this.selStart, this.selEnd - this.selStart) + : null : null : (actualResult = []); } @@ -158,9 +160,13 @@ export class NgxMaskService extends NgxMaskApplierService { if (!this.showMaskTyped || (this.showMaskTyped && this.hiddenInput)) { if (this.hiddenInput) { - return result && result.length - ? this.hideInput(result, this.maskExpression) - : result; + if (backspaced) { + return this.hideInput(result, this.maskExpression); + } + return ( + this.hideInput(result, this.maskExpression) + + this.maskIsShown.slice(result.length) + ); } return result; } @@ -196,7 +202,8 @@ export class NgxMaskService extends NgxMaskApplierService { justPasted: boolean, backspaced: boolean, // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-explicit-any - cb: (...args: any[]) => any = () => {} + cb: (...args: any[]) => any = () => { + } ): void { const formElement = this._elementRef?.nativeElement; if (!formElement) { @@ -330,8 +337,8 @@ export class NgxMaskService extends NgxMaskApplierService { if ( this.clearIfNotMatch && this.prefix.length + this.maskExpression.length + this.suffix.length !== - formElement.value.replace(this.placeHolderCharacter, MaskExpression.EMPTY_STRING) - .length + formElement.value.replace(this.placeHolderCharacter, MaskExpression.EMPTY_STRING) + .length ) { this.formElementProperty = ['value', MaskExpression.EMPTY_STRING]; this.applyMask('', this.maskExpression); @@ -518,9 +525,9 @@ export class NgxMaskService extends NgxMaskApplierService { } return value ? value.replace( - this._regExpForRemove(specialCharactersForRemove), - MaskExpression.EMPTY_STRING - ) + this._regExpForRemove(specialCharactersForRemove), + MaskExpression.EMPTY_STRING + ) : value; } @@ -541,8 +548,8 @@ export class NgxMaskService extends NgxMaskApplierService { private _retrieveSeparatorValue(result: string): string { const specialCharacters = Array.isArray(this.dropSpecialCharacters) ? this.specialCharacters.filter((v) => { - return (this.dropSpecialCharacters as string[]).includes(v); - }) + return (this.dropSpecialCharacters as string[]).includes(v); + }) : this.specialCharacters; return this._removeMask(result, specialCharacters); } @@ -646,4 +653,23 @@ export class NgxMaskService extends NgxMaskApplierService { public currentLocaleDecimalMarker(): string { return (1.1).toLocaleString().substring(1, 2); } + + public typeNumber(inputValue: string, mask: string): string { + const numberString = inputValue.toString(); + let maskedNumber = ''; + let numberIndex = 0; + + for (let i = 0; i < mask.length; i++) { + const maskChar = mask[i] as string; + + if (this.specialCharacters.includes(maskChar)) { + maskedNumber += maskChar; + } else if (maskChar === '0') { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + maskedNumber += numberString[numberIndex] || this.placeHolderCharacter; + numberIndex++; + } + } + return maskedNumber; + } } diff --git a/projects/ngx-mask-lib/src/test/secure-mask.spec.ts b/projects/ngx-mask-lib/src/test/secure-mask.spec.ts index b1a6c0f1..830693b9 100644 --- a/projects/ngx-mask-lib/src/test/secure-mask.spec.ts +++ b/projects/ngx-mask-lib/src/test/secure-mask.spec.ts @@ -151,8 +151,8 @@ describe('Directive: Mask (Secure)', () => { component.mask = 'XXX/X0/0000'; component.hiddenInput = true; component.showMaskTyped = true; - equal('98765', '***/*5', fixture); - equal('1234', '***/*', fixture); + equal('98765', '***/*5/____', fixture); + equal('1234', '***/*_/____', fixture); equal('', '___/__/____', fixture); }); @@ -174,4 +174,23 @@ describe('Directive: Mask (Secure)', () => { expect(component.form.value).toBe(inputValue); })); + + it('hideInput with showMaskTyped mask=XXXX', () => { + component.mask = 'XXXX'; + component.hiddenInput = true; + component.showMaskTyped = true; + equal('1', '*___', fixture); + equal('12', '**__', fixture); + equal('123', '***_', fixture); + equal('1234', '****', fixture); + }); + + it('hideInput with showMaskTyped mask=XX-XX', () => { + component.mask = 'XX-XX'; + component.hiddenInput = true; + component.showMaskTyped = true; + + equal('1234', '**-**', fixture); + }); + }); diff --git a/projects/ngx-mask-lib/src/test/separator.spec.ts b/projects/ngx-mask-lib/src/test/separator.spec.ts index 576f1578..e9cf18d1 100644 --- a/projects/ngx-mask-lib/src/test/separator.spec.ts +++ b/projects/ngx-mask-lib/src/test/separator.spec.ts @@ -964,4 +964,32 @@ describe('Separator: Mask', () => { expect(inputElement.selectionStart).toBe(4); expect(inputElement.value).toBe('123 456'); }); + + it('should change formValue separator.2', fakeAsync(() => { + component.mask = 'separator.2'; + component.leadZero = true; + const debugElement: DebugElement = fixture.debugElement.query(By.css('input')); + const inputTarget: HTMLInputElement = debugElement.nativeElement as HTMLInputElement; + spyOnProperty(document, 'activeElement').and.returnValue(inputTarget); + fixture.detectChanges(); + + component.form.setValue('10.2'); + tick(); + expect(inputTarget.value).toBe('10.20'); + expect(component.form.value).toBe('10.20'); + })); + + it('should change formValue separator.3', fakeAsync(() => { + component.mask = 'separator.3'; + component.leadZero = true; + const debugElement: DebugElement = fixture.debugElement.query(By.css('input')); + const inputTarget: HTMLInputElement = debugElement.nativeElement as HTMLInputElement; + spyOnProperty(document, 'activeElement').and.returnValue(inputTarget); + fixture.detectChanges(); + + component.form.setValue('10.2'); + tick(); + expect(inputTarget.value).toBe('10.200'); + expect(component.form.value).toBe('10.200'); + })); });