diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c11837e..360cc8cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +# 19.0.4(2024-12-13) + +### Feature + +- add input property instantPrefix + +### Fix + +- Fix ([#1477](https://github.com/JsDaddy/ngx-mask/issues/1477)) +- Fix ([#1476](https://github.com/JsDaddy/ngx-mask/issues/1476)) + # 19.0.3(2024-12-05) ### Contributing Fix diff --git a/USAGE.md b/USAGE.md index a29fdfdc..9e0932f8 100644 --- a/USAGE.md +++ b/USAGE.md @@ -132,12 +132,28 @@ pattern = { You can add prefix to you masked value + #### Usage ```html ``` +### instantPrefix + +The input property instantPrefix controls the display behavior of a prefix in the input. + +When set to true, the prefix is displayed even if the model is empty. +When set to false, the prefix only becomes visible when a value is present in the model. + +#### Usage + +```html + + +``` + + ### suffix (string) You can add suffix to you masked value diff --git a/package.json b/package.json index 6265dfd8..435286ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ngx-mask", - "version": "19.0.3", + "version": "19.0.4", "description": "Awesome ngx mask", "license": "MIT", "engines": { diff --git a/projects/ngx-mask-lib/package.json b/projects/ngx-mask-lib/package.json index 7abb7f1f..c78fd945 100644 --- a/projects/ngx-mask-lib/package.json +++ b/projects/ngx-mask-lib/package.json @@ -1,6 +1,6 @@ { "name": "ngx-mask", - "version": "19.0.3", + "version": "19.0.4", "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 b2bd5f2b..529f920d 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 @@ -53,6 +53,8 @@ export class NgxMaskApplierService { public keepCharacterPositions: NgxMaskConfig['keepCharacterPositions'] = this._config.keepCharacterPositions; + public instantPrefix: NgxMaskConfig['instantPrefix'] = this._config.instantPrefix; + private _shift = new Set(); public plusOnePosition = false; @@ -777,7 +779,7 @@ export class NgxMaskApplierService { }`; if (result.length === 0) { - res = !this.dropSpecialCharacters ? `${this.prefix}${result}` : `${result}`; + res = this.instantPrefix ? `${this.prefix}${result}` : `${result}`; } const isSpecialCharacterMaskFirstSymbol = diff --git a/projects/ngx-mask-lib/src/lib/ngx-mask.config.ts b/projects/ngx-mask-lib/src/lib/ngx-mask.config.ts index cb9c5a05..6fbcb7eb 100644 --- a/projects/ngx-mask-lib/src/lib/ngx-mask.config.ts +++ b/projects/ngx-mask-lib/src/lib/ngx-mask.config.ts @@ -18,6 +18,7 @@ export type NgxMaskConfig = { dropSpecialCharacters: boolean | string[] | readonly string[]; hiddenInput: boolean; validation: boolean; + instantPrefix: boolean; separatorLimit: string; apm: boolean; allowNegativeNumbers: boolean; @@ -50,6 +51,7 @@ export const initialConfig: NgxMaskConfig = { decimalMarker: ['.', ','], clearIfNotMatch: false, showMaskTyped: false, + instantPrefix: false, placeHolderCharacter: '_', dropSpecialCharacters: true, hiddenInput: false, 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 b58573fa..6cb07c9f 100644 --- a/projects/ngx-mask-lib/src/lib/ngx-mask.directive.ts +++ b/projects/ngx-mask-lib/src/lib/ngx-mask.directive.ts @@ -57,6 +57,7 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida public inputTransformFn = input(null); public outputTransformFn = input(null); public keepCharacterPositions = input(null); + public instantPrefix = input(null); public maskFilled = output(); @@ -107,6 +108,7 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida inputTransformFn, outputTransformFn, keepCharacterPositions, + instantPrefix, } = changes; if (mask) { if (mask.currentValue !== mask.previousValue && !mask.firstChange) { @@ -147,6 +149,10 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida if (apm && apm.currentValue) { this._maskService.apm = apm.currentValue; } + + if (instantPrefix) { + this._maskService.instantPrefix = instantPrefix.currentValue; + } if (prefix) { this._maskService.prefix = prefix.currentValue; } @@ -966,7 +972,7 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida this._maskService.isNumberValue = true; } - if (typeof inputValue !== 'string') { + if (typeof inputValue !== 'string' || value === null || typeof value === 'undefined') { inputValue = ''; } diff --git a/projects/ngx-mask-lib/src/test/add-prefix.spec.ts b/projects/ngx-mask-lib/src/test/add-prefix.spec.ts index e36beb7f..5029fa6c 100644 --- a/projects/ngx-mask-lib/src/test/add-prefix.spec.ts +++ b/projects/ngx-mask-lib/src/test/add-prefix.spec.ts @@ -159,4 +159,52 @@ describe('Directive: Mask (Add prefix)', () => { equal('KZ123123', 'KZ123 123', fixture); expect(component.form.value).toBe('KZ123 123'); }); + + it('should show prefix if value is empty mask 0000', () => { + component.mask.set('0000'); + component.prefix.set('+38 '); + component.instantPrefix.set(true); + + equal('', '+38 ', fixture); + equal('1', '+38 1', fixture); + equal('12', '+38 12', fixture); + equal('123', '+38 123', fixture); + equal('1234', '+38 1234', fixture); + }); + + it('should show prefix if value is empty mask 0000 with dropSpecialCharacter false', () => { + component.mask.set('0000'); + component.prefix.set('+38 '); + component.dropSpecialCharacters.set(false); + component.instantPrefix.set(true); + + equal('', '+38 ', fixture); + equal('1', '+38 1', fixture); + equal('12', '+38 12', fixture); + equal('123', '+38 123', fixture); + equal('1234', '+38 1234', fixture); + }); + + it('should doesnt show prefix if value is empty mask 0000', () => { + component.mask.set('0000'); + component.prefix.set('+38 '); + + equal('', '', fixture); + equal('1', '+38 1', fixture); + equal('12', '+38 12', fixture); + equal('123', '+38 123', fixture); + equal('1234', '+38 1234', fixture); + }); + + it('should doesnt show prefix if value is empty mask 0000 with dropSpecialCharacter false', () => { + component.mask.set('0000'); + component.prefix.set('+38 '); + component.dropSpecialCharacters.set(false); + + equal('', '', fixture); + equal('1', '+38 1', fixture); + equal('12', '+38 12', fixture); + equal('123', '+38 123', fixture); + equal('1234', '+38 1234', fixture); + }); }); diff --git a/projects/ngx-mask-lib/src/test/basic-logic.spec.ts b/projects/ngx-mask-lib/src/test/basic-logic.spec.ts index 8d76cadf..c9c2bc5f 100644 --- a/projects/ngx-mask-lib/src/test/basic-logic.spec.ts +++ b/projects/ngx-mask-lib/src/test/basic-logic.spec.ts @@ -648,7 +648,7 @@ describe('Directive: Mask', () => { expect(component.form.value).toBe('foo/257'); expect(component.form.valid).toBeFalse(); - equal('', 'foo/', fixture); + equal('', '', fixture); expect(component.form.value).toBe(''); }); @@ -1028,4 +1028,13 @@ describe('Directive: Mask', () => { equal('122', '12.2', fixture); equal('12.22', '12.2.', fixture); }); + + it('should show default state after reset control 0000', () => { + component.mask.set('0000'); + + equal('1234', '1234', fixture); + component.form.reset(); + expect(component.form.dirty).toBe(false); + expect(component.form.pristine).toBe(true); + }); }); diff --git a/projects/ngx-mask-lib/src/test/separator.spec.ts b/projects/ngx-mask-lib/src/test/separator.spec.ts index 6266affe..cc629b5f 100644 --- a/projects/ngx-mask-lib/src/test/separator.spec.ts +++ b/projects/ngx-mask-lib/src/test/separator.spec.ts @@ -1871,4 +1871,35 @@ describe('Separator: Mask', () => { equal('12345678910111215.9999', '12,345,678,910,111,215.99', fixture); expect(component.form.value).toBe('12345678910111215.99'); }); + + it('should show default state after reset control separator.2', () => { + component.mask.set('separator.2'); + component.thousandSeparator.set(','); + + equal('1234', '1,234', fixture); + component.form.reset(); + expect(component.form.dirty).toBe(false); + expect(component.form.pristine).toBe(true); + }); + + it('should show default state after reset control separator.0', () => { + component.mask.set('separator.0'); + component.thousandSeparator.set(','); + + equal('1234', '1,234', fixture); + component.form.reset(); + expect(component.form.dirty).toBe(false); + expect(component.form.pristine).toBe(true); + }); + + it('should show default state after reset control separator.2 and leadZero', () => { + component.mask.set('separator.2'); + component.thousandSeparator.set(','); + component.leadZero.set(true); + + equal('1234', '1,234', fixture); + component.form.reset(); + expect(component.form.dirty).toBe(false); + expect(component.form.pristine).toBe(true); + }); }); diff --git a/projects/ngx-mask-lib/src/test/utils/test-component.component.ts b/projects/ngx-mask-lib/src/test/utils/test-component.component.ts index c5e5b0c2..0448f47e 100644 --- a/projects/ngx-mask-lib/src/test/utils/test-component.component.ts +++ b/projects/ngx-mask-lib/src/test/utils/test-component.component.ts @@ -32,6 +32,7 @@ import { NgxMaskDirective } from 'ngx-mask'; [apm]="apm()" [validation]="validation()" [inputTransformFn]="inputTransformFn()" + [instantPrefix]="instantPrefix()" [outputTransformFn]="outputTransformFn()" [triggerOnMaskChange]="triggerOnMaskChange()" /> `, @@ -84,4 +85,5 @@ export class TestMaskComponent { public triggerOnMaskChange = signal( this._config.triggerOnMaskChange ); + public instantPrefix = signal(this._config.instantPrefix); }