diff --git a/projects/ngx-mask-lib/src/lib/mask-applier.service.ts b/projects/ngx-mask-lib/src/lib/mask-applier.service.ts index 5e860b43..1f7f4153 100644 --- a/projects/ngx-mask-lib/src/lib/mask-applier.service.ts +++ b/projects/ngx-mask-lib/src/lib/mask-applier.service.ts @@ -54,14 +54,14 @@ export class MaskApplierService { } public applyMask( - inputValue: string, + inputValue: string | object | boolean | null | undefined, maskExpression: string, position: number = 0, justPasted: boolean = false, backspaced: boolean = false, cb: (shift: number, backspaceShift: boolean) => void = () => {} ): string { - if (inputValue === undefined || inputValue === null || maskExpression === undefined) { + if (!maskExpression || typeof inputValue !== 'string') { return ''; } let cursor = 0; diff --git a/projects/ngx-mask-lib/src/lib/mask.directive.ts b/projects/ngx-mask-lib/src/lib/mask.directive.ts index 6df0ce17..9b4d82e7 100644 --- a/projects/ngx-mask-lib/src/lib/mask.directive.ts +++ b/projects/ngx-mask-lib/src/lib/mask.directive.ts @@ -249,6 +249,14 @@ export class MaskDirective implements ControlValueAccessor, OnChanges, Validator this._maskService.selEnd = el.selectionEnd; } + @HostListener('ngModelChange', ['$event']) + public onModelChange(value: any): void { + // on form reset we need to update the actualValue + if (!value && this._maskService.actualValue) { + this._maskService.actualValue = this._maskService.getActualValue(''); + } + } + @HostListener('paste') public onPaste() { this._justPasted = true; @@ -439,15 +447,16 @@ export class MaskDirective implements ControlValueAccessor, OnChanges, Validator inputValue = inputValue.value; } - if (inputValue === undefined) { - inputValue = ''; - } if (typeof inputValue === 'number') { inputValue = String(inputValue); inputValue = this.decimalMarker !== '.' ? inputValue.replace('.', this.decimalMarker) : inputValue; this._maskService.isNumberValue = true; } + if (typeof inputValue !== 'string') { + inputValue = ''; + } + this._inputValue = inputValue; this._setMask(); diff --git a/projects/ngx-mask-lib/src/lib/mask.service.ts b/projects/ngx-mask-lib/src/lib/mask.service.ts index 6c7b1188..06c95274 100644 --- a/projects/ngx-mask-lib/src/lib/mask.service.ts +++ b/projects/ngx-mask-lib/src/lib/mask.service.ts @@ -75,6 +75,9 @@ export class MaskService extends MaskApplierService { } else { actualResult = []; } + if (this.showMaskTyped) { + inputValue = this.removeMask(inputValue); + } newInputValue = this.actualValue.length && actualResult.length <= inputValue.length ? this.shiftTypedSymbols(actualResult.join('')) 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 52489eb7..916f22f9 100644 --- a/projects/ngx-mask-lib/src/test/secure-mask.spec.ts +++ b/projects/ngx-mask-lib/src/test/secure-mask.spec.ts @@ -122,4 +122,26 @@ describe('Directive: Mask (Secure)', () => { expect(fixture.nativeElement.querySelector('input').value).toBe('123/45/6789'); }); }); + + it('should not keep shadow copy when form reset', () => { + component.hiddenInput = true; + component.mask = 'XXX/X0/0000'; + equal('54321', '***/*1', fixture); + typeTest('1', fixture); + expect(component.form.value).toBe('1'); + component.form.reset(); + expect(component.form.value).toBe(null); + equal('2', '*', fixture); + expect(component.form.value).toBe('2'); + }); + + it('mask changes should work with null input', () => { + component.hiddenInput = true; + component.mask = '000/00/0000'; + equal('987654321', '987/65/4321', fixture); + component.form.reset(); + component.mask = 'XXX/X0/0000'; + equal('54321', '***/*1', fixture); + expect(component.form.value).toBe('54321'); + }); }); diff --git a/src/app/bugs/bugs.component.html b/src/app/bugs/bugs.component.html index 6069afc0..e098f095 100644 --- a/src/app/bugs/bugs.component.html +++ b/src/app/bugs/bugs.component.html @@ -149,7 +149,7 @@ type="text" placeholder="Secure input" [hiddenInput]="true" - mask="XXX-X0-0000" + [mask]="mask" formControlName="secureInput" id="SecureInput" /> diff --git a/src/app/bugs/bugs.component.ts b/src/app/bugs/bugs.component.ts index 40dd3299..3154bf89 100644 --- a/src/app/bugs/bugs.component.ts +++ b/src/app/bugs/bugs.component.ts @@ -1,14 +1,15 @@ -import { Component, OnDestroy } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; @Component({ templateUrl: './bugs.component.html', }) -export class BugsComponent implements OnDestroy { +export class BugsComponent implements OnInit, OnDestroy { public bugsForm: FormGroup; public submitted: boolean = false; - + public mask = 'XXX-XX-XXXX'; // Can be used as a takeUntil for any observables this component may subscribe to. e.g. a form control valueChanges private onDestroy$ = new Subject(); @@ -28,6 +29,19 @@ export class BugsComponent implements OnDestroy { this.onDestroy$.complete(); } + ngOnInit(): void { + this.bugsForm + .get('SecureInput') + ?.valueChanges.pipe(takeUntil(this.onDestroy$)) + .subscribe((value) => { + if (this.bugsForm.get('SecureInput')?.valid) { + this.mask = '000-00-0000'; + } else { + this.mask = 'XXX-X0-0000'; + } + }); + } + submitForm(): void { this.submitted = true; } diff --git a/src/styles.scss b/src/styles.scss index 3bd473ea..f59ae729 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -68,6 +68,7 @@ body { .mat-grid-list, .mat-grid-tile, +.mat-grid-tile-content, .mat-grid-tile .mat-figure { position: inherit !important; }