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);
}