Angular Tutorial - building an InputMask directive [1/*]

in #education6 years ago

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" />
Sort:  

Congratulations @geggi632! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 3 years!

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!