Angular - InputMask
<p dir="auto">It's curios that angular has no built in input mask. I think everyone who is writing business software comes to the point where you have to add a pre or suffix to an string or int value.<br />
The best example is any currency field which should look like a formated number (examples: $ 4.00 or 5,50€) and should be editable + bindable.
<p dir="auto">Now you have several options to accomplish this result.<br />
You can use the suffix/prefix feature from matInput but I think you will run in some styling issues and you are not very flexible.<br />
Maybe you are into pipes - why not use the angular built-in currency pipe? Try it.. you will run in some two way binding errors because the pipe transform the number into an string but doesn't translate it back..<br />
I searched a lot and found some interesting npm packages like:<br /><br />
If it fits your needs - great - it's working very good and it helped me a lot understanding how directives are working.<span>
<a href="https://www.npmjs.com/package/ngx-currency" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">https://www.npmjs.com/package/ngx-currency
<p dir="auto">Unfortunately I ran in some incompatibility and it all endet with building my own directive.<br />
This post should give you the base for your own inputMask which is easy to use and extend for your special needs.<br />
I will split this tutorial to several posts because free time is such a thing.. yeah you know.
<p dir="auto">First create a directive with the angular CLI:<br />
<code>ng g d <name> (i will use inputMask for this tutorial)
<p dir="auto">Dont forget to add it to the declarations section in your module if you didn't use angular CLI:<br />
<img src="https://images.hive.blog/768x0/https://cdn.steemitimages.com/DQmaCLaocvfsFmTcBoyyFawghsMQUqMTDH9sS9RFW43rRuh/image.png" srcset="https://images.hive.blog/768x0/https://cdn.steemitimages.com/DQmaCLaocvfsFmTcBoyyFawghsMQUqMTDH9sS9RFW43rRuh/image.png 1x, https://images.hive.blog/1536x0/https://cdn.steemitimages.com/DQmaCLaocvfsFmTcBoyyFawghsMQUqMTDH9sS9RFW43rRuh/image.png 2x" />
<p dir="auto">For testing just place an input anywhere in your html and add the directive:<br />
<code><input inputMask value='14'>
<p dir="auto">Now we should care about the config/options for your inputMask. You can add every parameter as an input but I will go with an model. Just create a new file or add it to your directive.<br />
I will go with this:
<pre><code>export interface IInputMaskOptions {
prefix?: string;
suffix?: string;
}
export class InputMaskOptions implements IInputMaskOptions {
prefix?: string;
suffix?: string;
constructor(data?: IInputMaskOptions) {
if (data) {
for (var property in data) {
if (data.hasOwnProperty(property))
(<any>this)[property] = (<any>data)[property];
}
}
}
}
<p dir="auto"><br /><span>Add your options model with the <a href="/@input">@Input decorator to your directive:
<pre><code>export class InputMaskDirective implements OnInit {
@Input() options: InputMaskOptions;
<p dir="auto"><br /><span>Now open the typescript file from the component you put your test input and create an options model for testing and bind it to the <a href="/@input">@Input from your decorator
<pre><code> options: InputMaskOptions = new InputMaskOptions({
prefix: 'steemIt',
suffix: 'tutorial'
});
<input inputMask [options]="options" value='14'>
<p dir="auto">Now we are able to configurate our directive and can start with the real fun.<br />
What we actually trying to achieve is that the input has 2 states.<br />
-idle: just showing the formated value<br />
-edit: if the input has focus - remove every suffix or prefix and let me just change the binded value.
<p dir="auto">We will start with the constructor - we will need access to the HTML Element so we have to inject Elementref:<br />
<code>constructor(private elementRef: ElementRef) { }
<p dir="auto">For easier access to the value of the input we will add getter and setter:
<pre><code> get rawValue(): string {
return this.elementRef.nativeElement.value;
}
set rawValue(value: string) {
this.elementRef.nativeElement.value = value;
}
<p dir="auto"><br />To recognize the focus and blur event add 2 HostListener:
<pre><code> @HostListener('focus') onFocus() {
}
@HostListener('blur') onBlur() {
}
<p dir="auto"><br />Now we need 2 methods to apply the mask and clear the mask:
<pre><code> applyMask(value: string): string {
return this.options.prefix + value + this.options.suffix;
}
clearMask(value: string): number {
let regTextDec = "\\."; //decimal seperator
let regTextThousand = "," //thousand seperator
var regDec = new RegExp(regTextDec, "g");
var regThousand = new RegExp(regTextThousand, "g");
let regNotRelevant = new RegExp("[^0-9" + regTextDec + regTextThousand + "]", "g");
let onlyNumber = value.replace(regNotRelevant, "");
let parseableNumber = onlyNumber.replace(regThousand, "").replace(regDec, ".");
return parseFloat(parseableNumber);
}
<p dir="auto"><br />and call it from our hostlisteners:
<pre><code> @HostListener('focus') onFocus() {
this.rawValue = this.clearMask(this.rawValue).toString();
}
@HostListener('blur') onBlur() {
this.rawValue = this.applyMask(this.rawValue);
}
<p dir="auto"><br />The result should like:<br />
<img src="https://images.hive.blog/0x0/https://cdn.steemitimages.com/DQmW5qHUwuBEGeDqQJ1ubZQqwhZWmFuR1npKbcmC3mari1Y/FirstAchievment.gif" alt="FirstAchievment.gif" />
<p dir="auto"><center>This was the first part of the tutorial - i hope you liked it!<br />
If you have any questions just ask in the comments :-)
<p dir="auto"><center><br />
<b>Greetings from Austria<br />
<img src="https://images.hive.blog/768x0/https://cdn.steemitimages.com/DQmdoU6VdR5LQQG1rqBR3j8Bmxen9jcvwHoufqMMLMvhFvx/DSC00390.jpg" alt="DSC00390.jpg" srcset="https://images.hive.blog/768x0/https://cdn.steemitimages.com/DQmdoU6VdR5LQQG1rqBR3j8Bmxen9jcvwHoufqMMLMvhFvx/DSC00390.jpg 1x, https://images.hive.blog/1536x0/https://cdn.steemitimages.com/DQmdoU6VdR5LQQG1rqBR3j8Bmxen9jcvwHoufqMMLMvhFvx/DSC00390.jpg 2x" />
Congratulations @geggi632! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Vote for @Steemitboard as a witness to get one more award and increased upvotes!