2

I am working on an Angular project and I have an object of type Project that contains the following values:

cost: 56896 and costHR: 27829

I want to modify the object using a form and bind the fields with ngModel to the attributes.

But the problem I am facing is that in the field, I want to display the number in a currency format (e.g. 56,896€) which is not compatible with the variable type which is float.

Can someone help me with a solution to this problem? I have tried using built-in Angular pipes and custom formatter and parser functions, but none of them seem to work as expected.

Any help would be greatly appreciated.

import { Component, OnInit } from '@angular/core';
import { CurrencyPipe } from '@angular/common';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [CurrencyPipe]
})
export class AppComponent implements OnInit {

  project = {
    cost: 56896,
    costRH: 27829
  }

  constructor(private currencyPipe: CurrencyPipe) { }

  ngOnInit() {
    this.project.cost = this.currencyPipe.transform(this.project.cost, 'EUR', 'symbol', '1.0-0');
    this.project.costRH = this.currencyPipe.transform(this.project.costRH, 'EUR', 'symbol', '1.0-0');
  }

  onBlur(event, projectProperty) {
    this.project[projectProperty] = this.currencyPipe.parse(event.target.value);
  }

}
<form>
  <label for="cost">Cost</label>
  <input [(ngModel)]="project.cost" (blur)="onBlur($event, 'cost')" [ngModelOptions]="{updateOn: 'blur'}" [value]="project.cost | currency:'EUR':'symbol':'1.0-0'">

  <label for="costRH">Cost RH</label>
  <input [(ngModel)]="project.costRH" (blur)="onBlur($event, 'costRH')" [ngModelOptions]="{updateOn: 'blur'}" [value]="project.costRH | currency:'EUR':'symbol':'1.0-0'">
</form>

What I expected: I expected the input fields to be formatted as currency (e.g. 56,896€) and for the corresponding properties in the 'projet' object (cost and costRH) to be updated with the parsed value when the input loses focus.

What happened instead: The value displayed in the input fields is not formatted as currency and the corresponding properties in the object are not being updated as expected.

RASFI
  • 288
  • 1
  • 13
  • Does this answer your question? [html5 input for money/currency](https://stackoverflow.com/questions/24163889/html5-input-for-money-currency) – Pvria Ansari Jan 26 '23 at 06:51
  • I would create a separate {{ currency }} next to the number input field and I would overlay them witch CSS. (put span over number input) Ofc make sure with paddings that the number isn't blocked out by the new span. (Also, you should probably try using some localization library) – Geri Dremák Jan 26 '23 at 06:56

2 Answers2

1

you can use a directive like

@Directive({
  selector: '[format]',
})
export class FormatDirective implements OnInit {
  format = 'N0';
  digitsInfo = '1.0-0';
  @Input() currency = '$';
  @Input() sufix = '';
  @Input() decimalCharacter = null;
  @Input('format') set _(value: string) {
    this.format = value;
    if (this.format == 'N2') this.digitsInfo = '1.2-2';

    const parts = value.split(':');
    if (parts.length > 1) {
      this.format = value[0];
      this.digitsInfo = parts[1];
    }
  }
  @HostListener('blur', ['$event.target']) blur(target: any) {
    target.value = this.parse(target.value);
  }
  @HostListener('focus', ['$event.target']) focus(target: any) {
    target.value = this.control.value;
  }
  ngOnInit() {
    setTimeout(() => {
      this.el.nativeElement.value = this.parse(this.el.nativeElement.value);
    });
  }
  constructor(
    @Inject(LOCALE_ID) private locale: string,
    private el: ElementRef,
    private control: NgControl
  ) {}
  parse(value: any) {
    let newValue = value;

    if (this.format == 'C2')
      newValue = formatCurrency(value, this.locale, this.currency);
    if (this.format == 'N2')
      newValue = formatNumber(value, this.locale, this.digitsInfo);
    if (this.format == 'N0')
      newValue = formatNumber(value, this.locale, this.digitsInfo);
    if (this.format == 'NX')
      newValue = formatNumber(value, this.locale, this.digitsInfo);
    if (this.decimalCharacter)
      return (
        newValue.replace('.', 'x').replace(',', '.').replace('x', ',') +
        this.sufix
      );

    return newValue + this.sufix;
  }

}

Works like

<input format="N0" [(ngModel)]="value"/>
<input format="N2" [(ngModel)]="value"/>
<input format="C2" [(ngModel)]="value"/>
<input format="N2" decimalCharacter='.' sufix=' €' [(ngModel)]="value"/>

The idea of the directive is that, when blur, change the "native Element", but not the value of the ngControl, when focus return the value of the ngControl

The stackblitz

Eliseo
  • 50,109
  • 4
  • 29
  • 67
0

I have used Numberal js for formatting numbers and it was awesome

Your desired format is this one '0,0[.]00 €'

check docs

Moein Moeinnia
  • 1,945
  • 3
  • 10
  • 26