5

I want to format input to USD currency as you type. The input will have 2 decimal places and will enter from right to left. Suppose if I type 54.60 it will be entered as $0.05-->$0.54-->$5.46-->$54.60. This PLUNKER exactly does this, but its in angular js. So far my directive looks like:

import {Directive, Output, EventEmitter} from '@angular/core';
import {NgControl} from '@angular/forms';

@Directive({
  selector: '[formControlName][currency]',
  host: {
    '(ngModelChange)': 'onInputChange($event)',
    '(keydown.backspace)':'onInputChange($event.target.value, true)'
  }
})
export class CurrencyMask {
  constructor(public model: NgControl) {}

  @Output() rawChange:EventEmitter<string> = new EventEmitter<string>();

  onInputChange(event: any, backspace: any) {
    // remove all mask characters (keep only numeric)
    var newVal = event.replace(/\D/g, '');
    var rawValue = newVal;
    var str = (newVal=='0'?'0.0':newVal).split('.');
    str[1] = str[1] || '0';
    newVal= str[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') + '.' + (str[1].length==1?str[1]+'0':str[1]);



    // set the new value
    this.model.valueAccessor.writeValue(newVal);
    this.rawChange.emit(rawValue)
  }
}

and in html it is being used as:

<input  name="cost" placeholder="cost" class="form-control"  type="text" currency formControlName="cost" (rawChange)="rawCurrency=$event">

Update:

what finally worked for me is:

onInputChange(event: any, backspace: any) {
    var newVal = (parseInt(event.replace(/[^0-9]/g, ''))/100).toLocaleString('en-US', { minimumFractionDigits: 2 });
    var rawValue = newVal;

    if(backspace) {
      newVal = newVal.substring(0, newVal.length - 1);
    }

    if(newVal.length == 0) {
      newVal = '';
    }
    else  {
      newVal = newVal;
    }
    // set the new value
    this.model.valueAccessor.writeValue(newVal);
    this.rawChange.emit(rawValue)
  }
2
  • could you please state your question? Commented Feb 7, 2017 at 14:38
  • I want to perform what the stated PLUNKER does in angular 2 , how do I enter the inputs from right to left and format it on the fly Commented Feb 7, 2017 at 14:41

2 Answers 2

3

on input change use the following

// remove dot and comma's, 123,456.78 -> 12345678
var strVal = myVal.replace(/\.,/g,'');
// change string to integer
var intVal = parseInt(strVal); 
// divide by 100 to get 0.05 when pressing 5 
var decVal = intVal / 100;
// format value to en-US locale
var newVal = decVal.toLocaleString('en-US', { minimumFractionDigits: 2 });

// or in singel line
var newVal = (parseInt(myVal.replace(/\.,/g, '')) / 100).toLocaleString('en-US', { minimumFractionDigits: 2 });

or

use currency pipe to format to USD format by using only

var newVal = (parseInt(myVal.replace(/\.,/g, '')) / 100)

Hope this helps.

Sign up to request clarification or add additional context in comments.

3 Comments

it's only allowing me to type 1 digit at a time, if I type7 then it shows 0.07; then if I type 8 it makes it 0...it keeps acting in this way
I assume you are getting the char from the event, in that case you need to append the new char at the end of strVal. the best way (of course this is my opinion) would be to use two way binding in angular2 whereby the input is updated with ngModel and update that variable after each keypress
var newVal = (parseInt(myVal.replace(/\.,/g, '') + newChar) / 100).toLocaleString('en-US', { minimumFractionDigits: 2 });
0

Angular has a formatCurrency method

https://angular.io/api/common/formatCurrency

Here's how I've used it in my code:

demand is a formControl

formatMoney(value: string) {
    this.demand.setValue(
        this.formatMoneyBase(value)
    );
}

formatMoneyBase(value: string = ''): string {
    return value.length ? formatCurrency(parseFloat(value.replace(/\D/g, '')), 'en', '$').replace('$', '') : '';
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.