diff --git a/CHANGELOG.md b/CHANGELOG.md
index fbecc764..9def9397 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,15 @@
+# 17.0.5(2024-03-25)
+
+### Fix
+
+https://github.com/JsDaddy/ngx-mask/issues/1295
+https://github.com/JsDaddy/ngx-mask/issues/1292
+https://github.com/JsDaddy/ngx-mask/issues/1314
+https://github.com/JsDaddy/ngx-mask/issues/1310
+https://github.com/JsDaddy/ngx-mask/issues/1304
+https://github.com/JsDaddy/ngx-mask/issues/1308
+https://github.com/JsDaddy/ngx-mask/issues/1299
+
# 17.0.4(2023-12-01)
### Feat
diff --git a/USAGE.md b/USAGE.md
index b1db0e93..5065f52f 100644
--- a/USAGE.md
+++ b/USAGE.md
@@ -17,7 +17,7 @@ Also, you can use mask pipe.
You could path any valid config options, for example thousandSeparator and suffix
```html
-{{value | mask: 'separator': {thousandSeparator: ',', suffix: ' sm'}}
+{{value | mask: 'separator': { thousandSeparator: ',', suffix: ' sm' } }}
```
### Examples
diff --git a/projects/ngx-mask-lib/package.json b/projects/ngx-mask-lib/package.json
index 52f4709d..3e6c603a 100644
--- a/projects/ngx-mask-lib/package.json
+++ b/projects/ngx-mask-lib/package.json
@@ -1,6 +1,6 @@
{
"name": "ngx-mask",
- "version": "17.0.4",
+ "version": "17.0.5",
"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 fdb571b7..3cd2b535 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
@@ -173,11 +173,12 @@ export class NgxMaskApplierService {
inputValue.length
)}`;
}
-
let value = '';
this.allowNegativeNumbers &&
inputValue.slice(cursor, cursor + 1) === MaskExpression.MINUS
- ? (value = inputValue.slice(cursor + 1, cursor + inputValue.length))
+ ? (value =
+ MaskExpression.MINUS +
+ inputValue.slice(cursor + 1, cursor + inputValue.length))
: (value = inputValue);
if (this.percentage(value)) {
result = this._splitPercentZero(inputValue);
@@ -718,6 +719,7 @@ export class NgxMaskApplierService {
if (backspaced) {
onlySpecial = inputArray.every((char) => this.specialCharacters.includes(char));
}
+
let res = `${this.prefix}${onlySpecial ? MaskExpression.EMPTY_STRING : result}${
this.showMaskTyped ? '' : this.suffix
}`;
@@ -804,7 +806,11 @@ export class NgxMaskApplierService {
private percentage = (str: string): boolean => {
const sanitizedStr = str.replace(',', '.');
- const value = Number(sanitizedStr);
+ const value = Number(
+ this.allowNegativeNumbers && str.includes(MaskExpression.MINUS)
+ ? sanitizedStr.slice(1, str.length)
+ : sanitizedStr
+ );
return !isNaN(value) && value >= 0 && value <= 100;
};
@@ -848,7 +854,6 @@ export class NgxMaskApplierService {
const precisionRegEx = new RegExp(
this._charToRegExpExpression(decimalMarker) + `\\d{${precision}}.*$`
);
-
const precisionMatch: RegExpMatchArray | null = inputValue.match(precisionRegEx);
const precisionMatchLength: number = (precisionMatch && precisionMatch[0]?.length) ?? 0;
if (precisionMatchLength - 1 > precision) {
@@ -929,6 +934,9 @@ export class NgxMaskApplierService {
}
private _splitPercentZero(value: string): string {
+ if (value === MaskExpression.MINUS && this.allowNegativeNumbers) {
+ return value;
+ }
const decimalIndex =
typeof this.decimalMarker === 'string'
? value.indexOf(this.decimalMarker)
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 e6fbd527..7a11d442 100644
--- a/projects/ngx-mask-lib/src/lib/ngx-mask.directive.ts
+++ b/projects/ngx-mask-lib/src/lib/ngx-mask.directive.ts
@@ -3,11 +3,11 @@ import {
Directive,
EventEmitter,
HostListener,
+ Input,
OnChanges,
Output,
SimpleChanges,
inject,
- input,
} from '@angular/core';
import {
ControlValueAccessor,
@@ -42,30 +42,54 @@ import { MaskExpression } from './ngx-mask-expression.enum';
exportAs: 'mask,ngxMask',
})
export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Validator {
- public maskExpression = input('', { alias: 'mask' });
- public specialCharacters = input([]);
- public patterns = input({});
- public prefix = input('');
- public suffix = input('');
- public thousandSeparator = input(' ');
- public decimalMarker = input('.');
- public dropSpecialCharacters = input(null);
- public hiddenInput = input(null);
- public showMaskTyped = input(null);
- public placeHolderCharacter = input(null);
- public shownMaskExpression = input(null);
- public showTemplate = input(null);
- public clearIfNotMatch = input(null);
- public validation = input(null);
- public separatorLimit = input(null);
- public allowNegativeNumbers = input(null);
- public leadZeroDateTime = input(null);
- public leadZero = input(null);
- public triggerOnMaskChange = input(null);
- public apm = input(null);
- public keepCharacterPositions = input(null);
- public inputTransformFn = input(null);
- public outputTransformFn = input(null);
+ // eslint-disable-next-line @angular-eslint/no-input-rename
+ @Input('mask') public maskExpression: string | undefined | null = '';
+
+ @Input() public specialCharacters: IConfig['specialCharacters'] = [];
+
+ @Input() public patterns: IConfig['patterns'] = {};
+
+ @Input() public prefix: IConfig['prefix'] = '';
+
+ @Input() public suffix: IConfig['suffix'] = '';
+
+ @Input() public thousandSeparator: IConfig['thousandSeparator'] = ' ';
+
+ @Input() public decimalMarker: IConfig['decimalMarker'] = '.';
+
+ @Input() public dropSpecialCharacters: IConfig['dropSpecialCharacters'] | null = null;
+
+ @Input() public hiddenInput: IConfig['hiddenInput'] | null = null;
+
+ @Input() public showMaskTyped: IConfig['showMaskTyped'] | null = null;
+
+ @Input() public placeHolderCharacter: IConfig['placeHolderCharacter'] | null = null;
+
+ @Input() public shownMaskExpression: IConfig['shownMaskExpression'] | null = null;
+
+ @Input() public showTemplate: IConfig['showTemplate'] | null = null;
+
+ @Input() public clearIfNotMatch: IConfig['clearIfNotMatch'] | null = null;
+
+ @Input() public validation: IConfig['validation'] | null = null;
+
+ @Input() public separatorLimit: IConfig['separatorLimit'] | null = null;
+
+ @Input() public allowNegativeNumbers: IConfig['allowNegativeNumbers'] | null = null;
+
+ @Input() public leadZeroDateTime: IConfig['leadZeroDateTime'] | null = null;
+
+ @Input() public leadZero: IConfig['leadZero'] | null = null;
+
+ @Input() public triggerOnMaskChange: IConfig['triggerOnMaskChange'] | null = null;
+
+ @Input() public apm: IConfig['apm'] | null = null;
+
+ @Input() public inputTransformFn: IConfig['inputTransformFn'] | null = null;
+
+ @Input() public outputTransformFn: IConfig['outputTransformFn'] | null = null;
+
+ @Input() public keepCharacterPositions: IConfig['keepCharacterPositions'] | null = null;
@Output() public maskFilled: IConfig['maskFilled'] = new EventEmitter();
@@ -98,7 +122,6 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
// eslint-disable-next-line @typescript-eslint/no-empty-function
public onTouch = () => {};
- //[TODO] andriiKamaldinov1 find better solution
public ngOnChanges(changes: SimpleChanges): void {
const {
maskExpression,
@@ -325,9 +348,10 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
? this._maskValue.length -
this._maskService.checkDropSpecialCharAmount(this._maskValue) -
counterOfOpt
- : this.prefix()
- ? this._maskValue.length + this.prefix().length - counterOfOpt
+ : this.prefix
+ ? this._maskValue.length + this.prefix.length - counterOfOpt
: this._maskValue.length - counterOfOpt;
+
if (array.length === 1) {
if (value.toString().length < length) {
return this._createValidationError(value);
@@ -339,7 +363,7 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
lastIndexArray &&
this._maskService.specialCharacters.includes(lastIndexArray[0] as string) &&
String(value).includes(lastIndexArray[0] ?? '') &&
- !this.dropSpecialCharacters()
+ !this.dropSpecialCharacters
) {
const special = value.split(lastIndexArray[0]);
return special[special.length - 1].length === lastIndexArray.length - 1
@@ -420,12 +444,12 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
: (el.selectionStart as number);
if (
- this.showMaskTyped() &&
- this.keepCharacterPositions() &&
+ this.showMaskTyped &&
+ this.keepCharacterPositions &&
this._maskService.placeHolderCharacter.length === 1
) {
const inputSymbol = el.value.slice(position - 1, position);
- const prefixLength = this.prefix().length;
+ const prefixLength = this.prefix.length;
const checkSymbols: boolean = this._maskService._checkSymbolMask(
inputSymbol,
this._maskService.maskExpression[position - 1 - prefixLength] ??
@@ -446,9 +470,9 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
if (!selectRangeBackspace) {
if (this._maskService.selStart === prefixLength) {
this._maskService.actualValue =
- this.prefix() +
+ this.prefix +
this._maskService.maskIsShown.slice(0, selEnd) +
- this._inputValue.split(this.prefix()).join('');
+ this._inputValue.split(this.prefix).join('');
} else if (
this._maskService.selStart ===
this._maskService.maskIsShown.length + prefixLength
@@ -458,9 +482,9 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
this._maskService.maskIsShown.slice(selStart, selEnd);
} else {
this._maskService.actualValue =
- this.prefix() +
+ this.prefix +
this._inputValue
- .split(this.prefix())
+ .split(this.prefix)
.join('')
.slice(0, selStart) +
this._maskService.maskIsShown.slice(selStart, selEnd) +
@@ -468,27 +492,27 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
selEnd + prefixLength,
this._maskService.maskIsShown.length + prefixLength
) +
- this.suffix();
+ this.suffix;
}
} else if (
!this._maskService.specialCharacters.includes(
this._maskService.maskExpression.slice(
- position - this.prefix().length,
- position + 1 - this.prefix().length
+ position - this.prefix.length,
+ position + 1 - this.prefix.length
)
) &&
selectRangeBackspace
) {
- if (selStart === 1 && this.prefix()) {
+ if (selStart === 1 && this.prefix) {
this._maskService.actualValue =
- this.prefix() +
+ this.prefix +
this._maskService.placeHolderCharacter +
el.value
- .split(this.prefix())
+ .split(this.prefix)
.join('')
- .split(this.suffix())
+ .split(this.suffix)
.join('') +
- this.suffix();
+ this.suffix;
position = position - 1;
} else {
const part1 = el.value.substring(0, position);
@@ -519,25 +543,25 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
} else if (checkSymbols) {
if (el.value.length === 1 && position === 1) {
this._maskService.actualValue =
- this.prefix() +
+ this.prefix +
inputSymbol +
this._maskService.maskIsShown.slice(
1,
this._maskService.maskIsShown.length
) +
- this.suffix();
+ this.suffix;
} else {
this._maskService.actualValue =
el.value.slice(0, position - 1) +
inputSymbol +
el.value
.slice(position + 1)
- .split(this.suffix())
+ .split(this.suffix)
.join('') +
- this.suffix();
+ this.suffix;
}
} else if (
- this.prefix() &&
+ this.prefix &&
el.value.length === 1 &&
position - prefixLength === 1 &&
this._maskService._checkSymbolMask(
@@ -547,13 +571,13 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
)
) {
this._maskService.actualValue =
- this.prefix() +
+ this.prefix +
el.value +
this._maskService.maskIsShown.slice(
1,
this._maskService.maskIsShown.length
) +
- this.suffix();
+ this.suffix;
}
}
}
@@ -577,7 +601,7 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
}
if (
this._maskService.maskExpression === MaskExpression.DAYS_MONTHS_YEARS &&
- this.leadZeroDateTime()
+ this.leadZeroDateTime
) {
if (
(position < 3 && Number(el.value) > 31 && Number(el.value) < 40) ||
@@ -586,10 +610,9 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
position = position + 2;
}
}
-
if (
this._maskService.maskExpression === MaskExpression.HOURS_MINUTES_SECONDS &&
- this.apm()
+ this.apm
) {
if (this._justPasted && el.value.slice(0, 2) === MaskExpression.DOUBLE_ZERO) {
el.value = el.value.slice(1, 2) + el.value.slice(2, el.value.length);
@@ -622,7 +645,7 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
// update position after applyValueChanges to prevent cursor on wrong position when it has an array of maskExpression
if (this._maskExpressionArray.length) {
if (this._code === MaskExpression.BACKSPACE) {
- position = this.specialCharacters().includes(
+ position = this.specialCharacters.includes(
this._inputValue.slice(position - 1, position)
)
? position - 1
@@ -688,8 +711,7 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
public onBlur(e: CustomKeyboardEvent): void {
if (this._maskValue) {
const el: HTMLInputElement = e.target as HTMLInputElement;
- const decimalMarker = this.decimalMarker();
- if (this.leadZero() && el.value.length > 0 && typeof decimalMarker === 'string') {
+ if (this.leadZero && el.value.length > 0 && typeof this.decimalMarker === 'string') {
const maskExpression = this._maskService.maskExpression;
const precision = Number(
this._maskService.maskExpression.slice(
@@ -698,16 +720,16 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
)
);
if (precision > 1) {
- el.value = this.suffix() ? el.value.split(this.suffix()).join('') : el.value;
- const decimalPart = el.value.split(decimalMarker)[1] as string;
- el.value = el.value.includes(decimalMarker)
+ el.value = this.suffix ? el.value.split(this.suffix).join('') : el.value;
+ const decimalPart = el.value.split(this.decimalMarker)[1] as string;
+ el.value = el.value.includes(this.decimalMarker)
? el.value +
MaskExpression.NUMBER_ZERO.repeat(precision - decimalPart.length) +
- this.suffix()
+ this.suffix
: el.value +
- decimalMarker +
+ this.decimalMarker +
MaskExpression.NUMBER_ZERO.repeat(precision) +
- this.suffix();
+ this.suffix;
this._maskService.actualValue = el.value;
}
}
@@ -815,29 +837,29 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
}
if (e.key === MaskExpression.BACKSPACE && (el.selectionStart as number) !== 0) {
// If specialChars is false, (shouldn't ever happen) then set to the defaults
- const specialCharacters = this.specialCharacters()?.length
- ? this.specialCharacters()
+ this.specialCharacters = this.specialCharacters?.length
+ ? this.specialCharacters
: this._config.specialCharacters;
if (
- this.prefix().length > 1 &&
- (el.selectionStart as number) <= this.prefix().length
+ this.prefix.length > 1 &&
+ (el.selectionStart as number) <= this.prefix.length
) {
- el.setSelectionRange(this.prefix().length, el.selectionEnd);
+ el.setSelectionRange(this.prefix.length, el.selectionEnd);
} else {
if (
this._inputValue.length !== (el.selectionStart as number) &&
(el.selectionStart as number) !== 1
) {
while (
- specialCharacters.includes(
+ this.specialCharacters.includes(
(
this._inputValue[(el.selectionStart as number) - 1] ??
MaskExpression.EMPTY_STRING
).toString()
) &&
- ((this.prefix().length >= 1 &&
- (el.selectionStart as number) > this.prefix().length) ||
- this.prefix().length === 0)
+ ((this.prefix.length >= 1 &&
+ (el.selectionStart as number) > this.prefix.length) ||
+ this.prefix.length === 0)
) {
el.setSelectionRange(
(el.selectionStart as number) - 1,
@@ -872,12 +894,12 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
}
}
if (
- !!this.suffix() &&
- this.suffix().length > 1 &&
- this._inputValue.length - this.suffix().length < (el.selectionStart as number)
+ !!this.suffix &&
+ this.suffix.length > 1 &&
+ this._inputValue.length - this.suffix.length < (el.selectionStart as number)
) {
el.setSelectionRange(
- this._inputValue.length - this.suffix().length,
+ this._inputValue.length - this.suffix.length,
this._inputValue.length
);
} else if (
@@ -902,9 +924,10 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
controlValue = controlValue.value;
}
if (controlValue !== null) {
- const inputTransformFn = this.inputTransformFn();
// eslint-disable-next-line no-param-reassign
- controlValue = inputTransformFn ? inputTransformFn(controlValue) : controlValue;
+ controlValue = this.inputTransformFn
+ ? this.inputTransformFn(controlValue)
+ : controlValue;
}
if (
@@ -936,11 +959,17 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
)
: inputValue;
}
+ if (
+ Array.isArray(this._maskService.decimalMarker) &&
+ this.decimalMarker === MaskExpression.DOT
+ ) {
+ this._maskService.decimalMarker = MaskExpression.COMMA;
+ }
if (
this._maskService.leadZero &&
inputValue &&
- this.maskExpression() &&
- this.dropSpecialCharacters() !== false
+ this.maskExpression &&
+ this.dropSpecialCharacters !== false
) {
// eslint-disable-next-line no-param-reassign
inputValue = this._maskService._checkPrecision(
@@ -954,10 +983,7 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
.toString()
.replace(MaskExpression.DOT, MaskExpression.COMMA);
}
- if (
- this.maskExpression()?.startsWith(MaskExpression.SEPARATOR) &&
- this.leadZero()
- ) {
+ if (this.maskExpression?.startsWith(MaskExpression.SEPARATOR) && this.leadZero) {
requestAnimationFrame(() => {
this._maskService.applyMask(
inputValue?.toString() ?? '',
@@ -982,7 +1008,7 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
(this._maskService.prefix || this._maskService.showMaskTyped))
) {
// Let the service we know we are writing value so that triggering onChange function won't happen during applyMask
- typeof this.inputTransformFn() !== 'function'
+ typeof this.inputTransformFn !== 'function'
? (this._maskService.writingValue = true)
: '';
this._maskService.formElementProperty = [
@@ -990,7 +1016,7 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
this._maskService.applyMask(inputValue, this._maskService.maskExpression),
];
// Let the service know we've finished writing value
- typeof this.inputTransformFn() !== 'function'
+ typeof this.inputTransformFn !== 'function'
? (this._maskService.writingValue = false)
: '';
} else {
@@ -1024,12 +1050,12 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
public checkSelectionOnDeletion(el: HTMLInputElement): void {
el.selectionStart = Math.min(
- Math.max(this.prefix().length, el.selectionStart as number),
- this._inputValue.length - this.suffix().length
+ Math.max(this.prefix.length, el.selectionStart as number),
+ this._inputValue.length - this.suffix.length
);
el.selectionEnd = Math.min(
- Math.max(this.prefix().length, el.selectionEnd as number),
- this._inputValue.length - this.suffix().length
+ Math.max(this.prefix.length, el.selectionEnd as number),
+ this._inputValue.length - this.suffix.length
);
}
@@ -1096,21 +1122,23 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
this._maskService.removeMask(this._inputValue)?.length <=
this._maskService.removeMask(mask)?.length;
if (test) {
- this._maskValue = this._maskService.maskExpression = mask.includes(
- MaskExpression.CURLY_BRACKETS_LEFT
- )
- ? this._maskService._repeatPatternSymbols(mask)
- : mask;
+ this._maskValue =
+ this.maskExpression =
+ this._maskService.maskExpression =
+ mask.includes(MaskExpression.CURLY_BRACKETS_LEFT)
+ ? this._maskService._repeatPatternSymbols(mask)
+ : mask;
return test;
} else {
const expression =
this._maskExpressionArray[this._maskExpressionArray.length - 1] ??
MaskExpression.EMPTY_STRING;
- this._maskValue = this._maskService.maskExpression = expression.includes(
- MaskExpression.CURLY_BRACKETS_LEFT
- )
- ? this._maskService._repeatPatternSymbols(expression)
- : expression;
+ this._maskValue =
+ this.maskExpression =
+ this._maskService.maskExpression =
+ expression.includes(MaskExpression.CURLY_BRACKETS_LEFT)
+ ? this._maskService._repeatPatternSymbols(expression)
+ : expression;
}
} else {
const check: boolean = this._maskService
@@ -1121,7 +1149,7 @@ export class NgxMaskDirective implements ControlValueAccessor, OnChanges, Valida
return this._maskService._checkSymbolMask(character, indexMask);
});
if (check) {
- this._maskValue = this._maskService.maskExpression = mask;
+ this._maskValue = this.maskExpression = this._maskService.maskExpression = mask;
return check;
}
}
diff --git a/projects/ngx-mask-lib/src/lib/ngx-mask.pipe.ts b/projects/ngx-mask-lib/src/lib/ngx-mask.pipe.ts
index 67cf6169..9288e956 100644
--- a/projects/ngx-mask-lib/src/lib/ngx-mask.pipe.ts
+++ b/projects/ngx-mask-lib/src/lib/ngx-mask.pipe.ts
@@ -1,6 +1,6 @@
import { inject, Pipe, PipeTransform } from '@angular/core';
-import { IConfig } from './ngx-mask.config';
+import { IConfig, NGX_MASK_CONFIG } from './ngx-mask.config';
import { NgxMaskService } from './ngx-mask.service';
import { MaskExpression } from './ngx-mask-expression.enum';
@@ -10,7 +10,7 @@ import { MaskExpression } from './ngx-mask-expression.enum';
standalone: true,
})
export class NgxMaskPipe implements PipeTransform {
- private readonly defaultOptions: Partial = {};
+ private readonly defaultOptions = inject(NGX_MASK_CONFIG);
private readonly _maskService = inject(NgxMaskService);
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 7f4cd908..ad6bee1c 100644
--- a/projects/ngx-mask-lib/src/lib/ngx-mask.service.ts
+++ b/projects/ngx-mask-lib/src/lib/ngx-mask.service.ts
@@ -124,7 +124,8 @@ export class NgxMaskService extends NgxMaskApplierService {
this.specialCharacters.indexOf(
this.maskExpression[position] ?? MaskExpression.EMPTY_STRING
) !== -1 &&
- this.showMaskTyped
+ this.showMaskTyped &&
+ !this.prefix
) {
newInputValue = this._currentValue;
}
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 36634901..a8dff092 100644
--- a/projects/ngx-mask-lib/src/test/add-prefix.spec.ts
+++ b/projects/ngx-mask-lib/src/test/add-prefix.spec.ts
@@ -121,4 +121,13 @@ describe('Directive: Mask (Add prefix)', () => {
equal('-12345', '-€1234.5', fixture);
equal('-123456', '-€1234.56', fixture);
});
+
+ it('should remove prefix when setValue', () => {
+ component.mask = '000 000';
+ component.prefix = 'KZ';
+ component.dropSpecialCharacters = true;
+ component.form.setValue('KZ123123');
+ equal('KZ123123', 'KZ123 123', fixture);
+ expect(component.form.value).toBe('123123');
+ });
});
diff --git a/projects/ngx-mask-lib/src/test/delete.cy-spec.ts b/projects/ngx-mask-lib/src/test/delete.cy-spec.ts
index 7b3ff2c2..4ce8e69f 100644
--- a/projects/ngx-mask-lib/src/test/delete.cy-spec.ts
+++ b/projects/ngx-mask-lib/src/test/delete.cy-spec.ts
@@ -201,4 +201,91 @@ describe('Directive: Mask (Delete)', () => {
.type('{backspace}')
.should('have.value', '12D : 34H : 56M : 78S');
});
+
+ it('should backspace with showMaskTyped and prefix', () => {
+ cy.mount(CypressTestMaskComponent, {
+ componentProperties: {
+ mask: '(000) 000-0000',
+ prefix: '+7 ',
+ showMaskTyped: true,
+ },
+ imports: [CypressTestMaskModule],
+ });
+
+ cy.get('#masked')
+ .type('1234567890')
+ .should('have.value', '+7 (123) 456-7890')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 16)
+ .should('have.value', '+7 (123) 456-789_')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 15)
+ .should('have.value', '+7 (123) 456-78__')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 14)
+ .should('have.value', '+7 (123) 456-7___')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 12)
+ .should('have.value', '+7 (123) 456-____')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 11)
+ .should('have.value', '+7 (123) 45_-____')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 10)
+ .should('have.value', '+7 (123) 4__-____')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 7)
+ .should('have.value', '+7 (123) ___-____')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 6)
+ .should('have.value', '+7 (12_) ___-____')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 5)
+ .should('have.value', '+7 (1__) ___-____')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 3)
+ .should('have.value', '+7 (___) ___-____');
+ });
+
+ it('should backspace with showMaskTyped and prefix', () => {
+ cy.mount(CypressTestMaskComponent, {
+ componentProperties: {
+ mask: '00 000 00 00',
+ prefix: '+32 ',
+ showMaskTyped: true,
+ },
+ imports: [CypressTestMaskModule],
+ });
+
+ cy.get('#masked')
+ .type('1234567890')
+ .should('have.value', '+32 12 345 67 89')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 15)
+ .should('have.value', '+32 12 345 67 8_')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 13)
+ .should('have.value', '+32 12 345 67 __')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 12)
+ .should('have.value', '+32 12 345 6_ __')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 10)
+ .should('have.value', '+32 12 345 __ __')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 9)
+ .should('have.value', '+32 12 34_ __ __')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 8)
+ .should('have.value', '+32 12 3__ __ __')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 6)
+ .should('have.value', '+32 12 ___ __ __')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 5)
+ .should('have.value', '+32 1_ ___ __ __')
+ .type('{backspace}')
+ .should('have.prop', 'selectionStart', 4)
+ .should('have.value', '+32 __ ___ __ __');
+ });
});
diff --git a/projects/ngx-mask-lib/src/test/drop-special-charaters.spec.ts b/projects/ngx-mask-lib/src/test/drop-special-charaters.spec.ts
index 6310cd0e..a3a6fcf3 100644
--- a/projects/ngx-mask-lib/src/test/drop-special-charaters.spec.ts
+++ b/projects/ngx-mask-lib/src/test/drop-special-charaters.spec.ts
@@ -65,4 +65,65 @@ describe('Directive: Mask (Drop special characters)', () => {
equal('1234567.89', '1 234 567.89', fixture);
expect(component.form.value).toBe(1234567.89);
});
+
+ it('dropSpecialCharacter test for valid', () => {
+ component.mask = '(000) 000-0000';
+ component.dropSpecialCharacters = true;
+ component.validation = true;
+ equal('1', '(1', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('12', '(12', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('123', '(123', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('1234', '(123) 4', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('12345', '(123) 45', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('123456', '(123) 456', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('1234567', '(123) 456-7', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('12345678', '(123) 456-78', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('123456789', '(123) 456-789', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('1234567890', '(123) 456-7890', fixture);
+ expect(component.form.valid).toBe(true);
+ });
+
+ it('dropSpecialCharacter = false test for valid', () => {
+ component.mask = '(000) 000-0000';
+ component.dropSpecialCharacters = true;
+ component.validation = true;
+ equal('1', '(1', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('12', '(12', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('123', '(123', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('1234', '(123) 4', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('12345', '(123) 45', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('123456', '(123) 456', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('1234567', '(123) 456-7', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('12345678', '(123) 456-78', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('123456789', '(123) 456-789', fixture);
+ expect(component.form.valid).toBe(false);
+ equal('1234567890', '(123) 456-7890', fixture);
+ expect(component.form.valid).toBe(true);
+ });
+
+ it('dropSpecialCharacter = true test for valid with setValue', () => {
+ component.mask = '(000) 000-0000';
+ component.dropSpecialCharacters = true;
+ component.validation = true;
+ component.form.setValue('1234567890');
+ equal('1234567890', '(123) 456-7890', fixture);
+ expect(component.form.valid).toBe(true);
+ });
});
diff --git a/projects/ngx-mask-lib/src/test/mask.pipe.spec.ts b/projects/ngx-mask-lib/src/test/mask.pipe.spec.ts
index c7ae6ff2..a2e6cdf3 100644
--- a/projects/ngx-mask-lib/src/test/mask.pipe.spec.ts
+++ b/projects/ngx-mask-lib/src/test/mask.pipe.spec.ts
@@ -351,5 +351,15 @@ describe('Pipe: Mask', () => {
});
expect(value).toEqual('3.000');
});
- //TODO(inepipepnko): need cover all config options
+
+ it('should show second pipe without suffix', () => {
+ const valueWithSuffix: string | number = maskPipe.transform('55555', '00 (000)', {
+ suffix: ' DDD',
+ });
+ const valueWithPrefix: string | number = maskPipe.transform('55555', '00 (000)', {
+ prefix: 'DDD ',
+ });
+ expect(valueWithSuffix).toEqual('55 (555) DDD');
+ expect(valueWithPrefix).toEqual('DDD 55 (555)');
+ });
});
diff --git a/projects/ngx-mask-lib/src/test/percent.spec.ts b/projects/ngx-mask-lib/src/test/percent.spec.ts
index fd639b3f..3e62d808 100644
--- a/projects/ngx-mask-lib/src/test/percent.spec.ts
+++ b/projects/ngx-mask-lib/src/test/percent.spec.ts
@@ -227,4 +227,77 @@ describe('Directive: Mask (Percent)', () => {
equal('12,221', '12,221%', fixture);
expect(component.form.value).toBe('12.221');
});
+
+ it('percent with allowNegative = true', () => {
+ component.mask = 'percent';
+ component.allowNegativeNumbers = true;
+
+ equal('-', '-', fixture);
+ equal('-1', '-1', fixture);
+ equal('-12', '-12', fixture);
+ expect(component.form.value).toBe('-12');
+ });
+
+ it('percent 2 with allowNegative = true', () => {
+ component.mask = 'percent.2';
+ component.allowNegativeNumbers = true;
+
+ equal('-', '-', fixture);
+ equal('-1', '-1', fixture);
+ equal('-12', '-12', fixture);
+ equal('-12.3', '-12.3', fixture);
+ equal('-12.34', '-12.34', fixture);
+ expect(component.form.value).toBe('-12.34');
+ });
+
+ it('percent 3 with allowNegative = true', () => {
+ component.mask = 'percent.3';
+ component.allowNegativeNumbers = true;
+
+ equal('-', '-', fixture);
+ equal('-1', '-1', fixture);
+ equal('-12', '-12', fixture);
+ equal('-12.3', '-12.3', fixture);
+ equal('-12.34', '-12.34', fixture);
+ equal('-12.345', '-12.345', fixture);
+ expect(component.form.value).toBe('-12.345');
+ });
+
+ it('percent with allowNegative = true, decimalMarker = ,', () => {
+ component.mask = 'percent';
+ component.decimalMarker = ',';
+ component.allowNegativeNumbers = true;
+
+ equal('-', '-', fixture);
+ equal('-1', '-1', fixture);
+ equal('-12', '-12', fixture);
+ expect(component.form.value).toBe('-12');
+ });
+
+ it('percent 2 with allowNegative = true, decimalMarker = ,', () => {
+ component.mask = 'percent.2';
+ component.decimalMarker = ',';
+ component.allowNegativeNumbers = true;
+
+ equal('-', '-', fixture);
+ equal('-1', '-1', fixture);
+ equal('-12', '-12', fixture);
+ equal('-12,3', '-12,3', fixture);
+ equal('-12,34', '-12,34', fixture);
+ expect(component.form.value).toBe('-12.34');
+ });
+
+ it('percent 3 with allowNegative = true, decimalMarker = ,', () => {
+ component.mask = 'percent.3';
+ component.allowNegativeNumbers = true;
+ component.decimalMarker = ',';
+
+ equal('-', '-', fixture);
+ equal('-1', '-1', fixture);
+ equal('-12', '-12', fixture);
+ equal('-12,3', '-12,3', fixture);
+ equal('-12,34', '-12,34', fixture);
+ equal('-12,345', '-12,345', fixture);
+ expect(component.form.value).toBe('-12.345');
+ });
});
diff --git a/projects/ngx-mask-lib/src/test/separator.spec.ts b/projects/ngx-mask-lib/src/test/separator.spec.ts
index 9f7e041d..807ee99b 100644
--- a/projects/ngx-mask-lib/src/test/separator.spec.ts
+++ b/projects/ngx-mask-lib/src/test/separator.spec.ts
@@ -1447,4 +1447,142 @@ describe('Separator: Mask', () => {
equal('-.34', '-0.34', fixture);
equal('-.345', '-0.345', fixture);
}));
+
+ it('separator.2 thousandSeparator = . should display correct value if decimalMarker is array 12345.67', fakeAsync(() => {
+ component.mask = 'separator.2';
+ component.thousandSeparator = '.';
+ 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(1255.78);
+ tick();
+ fixture.detectChanges();
+ requestAnimationFrame(() => {
+ expect(inputTarget.value).toBe('1.255,78');
+ });
+ }));
+
+ it('separator.3 thousandSeparator = . should display correct value if decimalMarker is array 12345.67', fakeAsync(() => {
+ component.mask = 'separator.3';
+ component.thousandSeparator = '.';
+ 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(1255.78);
+ tick();
+ requestAnimationFrame(() => {
+ expect(inputTarget.value).toBe('1.255,78');
+ });
+ }));
+
+ it('separator.1 thousandSeparator = . should display correct value if decimalMarker is array 12345.67', fakeAsync(() => {
+ component.thousandSeparator = '.';
+ component.mask = 'separator.1';
+ 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(1255.78);
+ tick();
+ requestAnimationFrame(() => {
+ expect(inputTarget.value).toBe('1.255,78');
+ });
+ }));
+
+ it('separator.2 thousandSeparator = , should display correct value if decimalMarker is array 12345.67', fakeAsync(() => {
+ const debugElement: DebugElement = fixture.debugElement.query(By.css('input'));
+ const inputTarget: HTMLInputElement = debugElement.nativeElement as HTMLInputElement;
+ component.mask = 'separator.2';
+ component.thousandSeparator = ',';
+ spyOnProperty(document, 'activeElement').and.returnValue(inputTarget);
+ fixture.detectChanges();
+
+ component.form.setValue(1255.78);
+ tick();
+
+ expect(inputTarget.value).toBe('1,255.78');
+ }));
+
+ it('separator.3 thousandSeparator = , should display correct value if decimalMarker is array 12345.67', fakeAsync(() => {
+ component.mask = 'separator.3';
+ component.thousandSeparator = ',';
+ 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(1255.78);
+ tick();
+
+ expect(inputTarget.value).toBe('1,255.78');
+ }));
+
+ it('separator.1 thousandSeparator = , should display correct value if decimalMarker is array 12345.67', fakeAsync(() => {
+ component.mask = 'separator.1';
+ component.thousandSeparator = ',';
+ 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(1255.78);
+ tick();
+
+ expect(inputTarget.value).toBe('1,255.7');
+ }));
+
+ it('separator.2 thousandSeparator = . leadZero should display correct value if decimalMarker is array 12345.67', fakeAsync(() => {
+ component.mask = 'separator.2';
+ component.thousandSeparator = '.';
+ 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(1255.78);
+ tick();
+ requestAnimationFrame(() => {
+ expect(inputTarget.value).toBe('1.255,78');
+ });
+ }));
+
+ it('separator.3 thousandSeparator = . leadZero should display correct value if decimalMarker is array 12345.67', fakeAsync(() => {
+ component.mask = 'separator.3';
+ component.thousandSeparator = '.';
+ 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(1255.78);
+ tick();
+ requestAnimationFrame(() => {
+ expect(inputTarget.value).toBe('1.255,780');
+ });
+ }));
+
+ it('separator.1 thousandSeparator = . leadZero should display correct value if decimalMarker is array 12345.67', fakeAsync(() => {
+ component.thousandSeparator = '.';
+ component.mask = 'separator.1';
+ 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(1255.78);
+ tick();
+ requestAnimationFrame(() => {
+ expect(inputTarget.value).toBe('1.255,78');
+ });
+ }));
});
diff --git a/src/app/options/options.component.html b/src/app/options/options.component.html
index 8c74c362..47bb32a3 100644
--- a/src/app/options/options.component.html
+++ b/src/app/options/options.component.html
@@ -100,6 +100,7 @@
mask="{{ ex._mask || '' }}"
[thousandSeparator]="ex._thousandSeparator || ' '"
[formControl]="ex.control.form"
+ [(ngModel)]="ex.control.model"
[decimalMarker]="ex._decimalMarker || '.'"
[leadZero]="ex._leadZero || null"
class="customDarkInput bg-black white span" />
diff --git a/src/libraries b/src/libraries
index 62334a2c..f402f517 160000
--- a/src/libraries
+++ b/src/libraries
@@ -1 +1 @@
-Subproject commit 62334a2c1cb5d45b3440c01f978915f8017fba8e
+Subproject commit f402f51789609e8de8500d39ff80cdcb68f89bb9