2

I am trying to create a directive that will format the input value to a currency format.

I am able to do what I have to do on focus and on blur, and in the ngOnInit hook (and any other hook), the input element does not yet have any values applied to it.

How do I "watch" for the input's value, and format it when it's initial value is applied?

Here is my directive:

import {
  Input,
  Directive,
  HostListener,
  ElementRef,
  Renderer,
  OnInit
} from '@angular/core';
import { NgModel } from '@angular/forms';
import { CurrencyPipe } from '@angular/common';

@Directive({
  selector: '[currencyInput]',
  providers: [NgModel],
  host: {
    '(input)': 'onInputChange()'
  }
})
export class CurrencyInputDirective implements OnInit {
  @Input() ngModel: number;

  private elem: HTMLInputElement;

  constructor(
    private el: ElementRef,
    private render: Renderer,
    private currencyPipe: CurrencyPipe,
    private model: NgModel,
  ) {
    this.elem = el.nativeElement;
  }

  ngOnInit() {
    this.elem.value = this.currencyPipe.transform(parseInt(this.elem.value), 'USD', true);
  }

  @HostListener('focus', ['$event.target.value'])
  onFocus(value: string) {
    this.elem.value = value.replace(/\,/g, '');
  }

  @HostListener('blur', ['$event.target.value'])
  onBlur(value: string) {
    this.elem.value = this.currencyPipe.transform(parseInt(value), 'USD', true);
  }
}

3 Answers 3

1
  ngAfterContentInit() {

    this.model.valueChanges.subscribe(value => {
      if(value) {
        const parsed = parseInt(value.replace('$', ""));
        this.model.valueAccessor.writeValue(new CurrencyPipe().transform(parsed, 'USD', true));
      }
    })
  }

In your template:

<div>
  <input type="text" currencyInput [ngModel]="initModel" name="number"/>
</div>
Sign up to request clarification or add additional context in comments.

1 Comment

I should have mentioned that I have tried all lifecycle hooks, and I always get empty value.
1

One possibility is to bind to a getter/setter method that will transform the field to the correct format, and then return it back to the original format after it is modified, as per below

typescript:

 AnnualRevenue: number;
  get AnnualRevenueFormatted():string{
    return  this.AnnualRevenue !== undefined ?  `$${this.AnnualRevenue.toLocaleString()}`: '$0';
  }

  // strip out all the currency information and apply to Annual Revenue
  set AnnualRevenueFormatted(val: string) {
    const revenueVal = val.replace(/[^\d]/g, '');
    this.AnnualRevenue = parseInt(revenueVal);
  } 

and in the component view

<input type="text" class="text-input" [(ngModel)]="accountInfo.AnnualRevenueFormatted"  />

Comments

0

On my directive I have applied the solution mentioned in this post:

ngAfterContentInit() {
    this.model.valueChanges.subscribe(value => {
        if (value) {
            const parsed = parseInt(value.replace('$', ""));
            this.model.valueAccessor.writeValue(new CurrencyPipe().transform(parsed, 'USD', true));
        }
    })
}

and it works for me.

See my Post : Directive display ng-model input value as currency in angular

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.