Search code examples
angularcurrency-pipe

How to get the amount converted to currency pipe value after getting error message in angular8


i am using currency pipe in blur event. But it works fine for the first time, when i get an error message of validation, if i delete few numbers and come out, it wont be formatted to the currency format remains in the format what user have deleted. For example i gave this number: 36543265 so when i came out of the input it is formatted to $36,543,265.00, with the validation error message. So if i delete 265.00 from $36,543,265.00 , i still have the error validation message. so the validation error message went off and stayed with this format $36,543 but it didn't come to the proper format. How do i make it to proper currency pipe format of USD, after clearing the validation message.

How can i make it to be formatted properly based on user deletion of values.

TS:

public transformAmount(element, name) {
  if (name == "amount") {
    let formattedAmount = this.currencyPipe.transform(this.eoInfoForm.value.amount, 'USD');
    element.target.value = formattedAmount;
    this.eoInfoForm.get('amount').setValue(formattedAmount);
    if (this.eoInfoForm.get('amount').status === 'VALID') {
      this.amt = false; 
    } 
    else {
      this.amt = true;
    } 
  } 
}

HTML:

 <input type="text" class="form-control" placeholder="Amount in dolars"
                    formControlName="amount" autocomplete="off" maxlength="8" allowNumberOnly (blur)="transformAmount($event,'amount')" [ngClass]="{ 'is-invalid': amt  && eoInfo.amount.invalid }">
                    <div *ngIf="amt && eoInfo.amount.invalid" class="invalid-feedback">
                        <div *ngIf="amt && eoInfo.amount.invalid">Maximum of 8 characters including $ is allowed</div>
                      </div>

DEMO: DEMO


Solution

  • you can write a somewhat simple directive to do this:

    import { Directive, HostListener, ElementRef, OnInit, Input } from "@angular/core";
    import { CurrencyPipe } from '@angular/common';
    
    @Directive({ selector: "[currencyInput]" })
    export class CurrencyInputDirective implements OnInit {
    
      // build the regex based on max pre decimal digits allowed
      private regexString(max?: number) {
        const maxStr = max ? `{0,${max}}` : `+`;
        return `^(\\d${maxStr}(\\.\\d{0,2})?|\\.\\d{0,2})$`
      }
      private digitRegex: RegExp;
      private setRegex(maxDigits?: number) {
        this.digitRegex = new RegExp(this.regexString(maxDigits), 'g')
      }
      @Input()
      set maxDigits(maxDigits: number) {
        this.setRegex(maxDigits);
      } 
    
      private el: HTMLInputElement;
    
      constructor(
        private elementRef: ElementRef,
        private currencyPipe: CurrencyPipe
      ) {
        this.el = this.elementRef.nativeElement;
        this.setRegex();
      }
    
      ngOnInit() {
        this.el.value = this.currencyPipe.transform(this.el.value, 'USD');
      }
    
      @HostListener("focus", ["$event.target.value"])
      onFocus(value) {
        // on focus remove currency formatting
        this.el.value = value.replace(/[^0-9.]+/g, '')
      }
    
      @HostListener("blur", ["$event.target.value"])
      onBlur(value) {
        // on blur, add currency formatting
        this.el.value = this.currencyPipe.transform(value, 'USD');
      }
    
      // variable to store last valid input
      private lastValid = '';
      @HostListener('input', ['$event'])
      onInput(event) {
        // on input, run regex to only allow certain characters and format
        const cleanValue = (event.target.value.match(this.digitRegex) || []).join('')
        if (cleanValue || !event.target.value)
          this.lastValid = cleanValue
        this.el.value = cleanValue || this.lastValid
      }
    }
    

    the directive converts the value to a number on focus and back to a formatted currency string on blur.

    use like:

    <input type="text" class="form-control" placeholder="Amount in dolars" autocomplete="off"
      formControlName="amount" currencyInput maxDigits="9" 
      [ngClass]="{ 'is-invalid': eoInfo.amount.dirty  && eoInfo.amount.invalid }">
    

    blitz: https://stackblitz.com/edit/angular-csyslb?file=src%2Fapp%2Fcurrency-input.directive.ts