0

I have an Ionic 3 App where I want to format all currency input field to a formal way. If I input 10,000 it should show to the field like this: PHP 10,000.00 and if hundreds it should show like this: PHP 100.00.

I also want to handle the backspace or clear button in Ionic when inputting a field so I can handle that in Android or iOS which I couldn't google to find some solutions or answer.

I already have found some reference in jQuery style with a jsfiddle on it.

But when I translate the code into Angular/Ionic way it didn't solve my problem.

Here is my code below in my ts file

handleCurrency(e) {
    console.log(e)
    if (e.keyCode == 8 && this.form.value.amount.length > 0) {
      this.form.value.amount = this.form.value.amount.slice(0, this.form.value.amount.length - 1); //remove last digit
      this.form.value.amount = this.formatNumber(this.form.value.amount);
    }
    else {
      let key = this.getKeyValue(e.keyCode);
      if (key) {
        this.form.value.amount += key; //add actual digit to the input string
        this.form.value.amount = this.formatNumber(this.form.value.amount); //format input string and set the input box value to it
      }
    }
    // return false;
  }

  getKeyValue(keyCode) {
    if (keyCode > 57) { //also check for numpad keys
      keyCode -= 48;
    }
    if (keyCode >= 48 && keyCode <= 57) {
      return String.fromCharCode(keyCode);
    }
  }

  formatNumber(input) {
    if (isNaN(parseFloat(input))) {
      return "0.00"; //if the input is invalid just set the value to 0.00
    }
    let num = parseFloat(input);
    return (num / 100).toFixed(2); //move the decimal up to places return a X.00 format
  }

and in my html

  <ion-input type="number" formControlName="amount" min="0.01" step="0.01" value="0.00" (keypress)="handleCurrency($event)"  placeholder=""></ion-input>

There are no errors in the code. But it doesn't work or it didn't automatically put decimal place between hundreds or thousands.

Can someone shed some light for me? Thanks in advance.

KnowledgeSeeker
  • 1,058
  • 2
  • 19
  • 44

2 Answers2

0

I found a package that solved my problem. I used ng2-currency-mask to set up your desired currency format. But still had the problem on backspace or clear button on Android and iOS on how to handle it. By default it always return 229 keyCode

KnowledgeSeeker
  • 1,058
  • 2
  • 19
  • 44
0

I might be too late for OP, but hoping my solution will help future visitors. I have also written a blog on medium to further detail the solution. Full source code can be found on github


Solution

By using the angular data binding, currency pipe & native ion-input, a custom currency input box can be easily implemented.

enter image description here

First, we will create a reusable input component:

number-input.component.html

<ion-item (click)="openInput()">
    {{ formattedAmount }}
    <ion-input name="dummyFacade" id="dummyFacade" #dummyFacade type="number" inputmode="numeric"
        (keyup)="handleKeyUp($event)" (ionInput)="handleInput($event)"></ion-input>
</ion-item>

number-input.component.js

@Component({
  selector: 'app-number-input',
  templateUrl: './number-input.component.html',
  styleUrls: ['./number-input.component.scss'],
  providers: [CurrencyPipe]
})
export class NumberInputComponent implements OnInit {

  private static BACKSPACE_KEY = 'Backspace';
  private static BACKSPACE_INPUT_TYPE = 'deleteContentBackward';

  @ViewChild('dummyFacade', {static: false}) private dummyFacade: IonInput;

  @Input() precision: number;

  @Input() amount: string;

  @Output() amountEntered = new EventEmitter<number>();

  constructor(private currencyPipe: CurrencyPipe) { }

  ngOnInit() {
    if (this.amount && this.amount.trim() !== '') {
      this.amountEntered.emit(+this.amount);
    }
  }

  handleKeyUp(event: KeyboardEvent) {
    // this handles keyboard input for backspace
    if (event.key === NumberInputComponent.BACKSPACE_KEY) {
      this.delDigit();
    }
  }

  handleInput(event: CustomEvent) {
    this.clearInput();
    // check if digit
    if (event.detail.data && !isNaN(event.detail.data)) {
      this.addDigit(event.detail.data);
    } else if (event.detail.inputType === NumberInputComponent.BACKSPACE_INPUT_TYPE) {
      // this handles numpad input for delete/backspace
      this.delDigit();
    }
  }

  private addDigit(key: string) {
    this.amount = this.amount + key;
    this.amountEntered.emit(+this.amount);
  }

  private delDigit() {
    this.amount = this.amount.substring(0, this.amount.length - 1);
    this.amountEntered.emit(+this.amount);
  }

  private clearInput() {
    this.dummyFacade.value = CONSTANTS.EMPTY; // ensures work for mobile devices
    // ensures work for browser
    this.dummyFacade.getInputElement().then((native: HTMLInputElement) => {
      native.value = CONSTANTS.EMPTY;
    });
  }

  get formattedAmount(): string {
    return this.currencyPipe.transform(+this.amount / Math.pow(10, this.precision));
  }

  openInput() {
    this.dummyFacade.setFocus();
  }

}
  • The component expects precision & initial amount from caller page, and outputs user entered/modified raw data.
  • Inside the component, ion-item encapsulates string field formattedAmount to display currency formatted value and ion-input to capture user input.
  • By handling both events ionInput & keyup of ion-input, we are first deriving the formattedAmount field using currency pipe and simultaneously clean slating the input box respectively at each keystroke of user. Ofcourse ignoring any non-numeric keyboard input. This creates the illusion of pretty formatted currency input box.
  • To help illudes the display text & input box as one entity, trigger the ion-input focus on click of the ion-item.
  • Using the EventEmitter to ouput the raw user input to the calling parent page.

Then, we will use it across any page where user input for amount in currency format is required:

app.page.html

<ion-content>
  <app-number-input [precision]="precision" [amount]="''" (amountEntered)="amountChanged($event)"></app-number-input> 
</ion-content>

app.page.ts

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {

  amount = 0;

  precision = 2;

  entry;
  constructor() {}

  amountChanged(event: number) {
    this.amount = event;
  }
}
  • Pass the required precision & initial amount.
  • Listen to the output event to capture the raw data for calculation.
Amith Kumar
  • 4,400
  • 1
  • 21
  • 28