1

I am trying to use a currency pipe in an input field that the user. So if the user enters 1234, it will reformat to 1,234.00.

I've found a good solution to this here: https://stackoverflow.com/a/50862298/1581924

This works the first time the user enters a number, but if the user re-types the same number, the input pipe is not applied the second time.

Example:

Type: 1234

Result: refomats to 1,234.00 (expected behavior)

Delete 1,234.00 and type 1234 again.

Result: input is not reformatted and left at 1234 (not expected behavior)

Example of code that exhibits the problem: https://stackblitz.com/edit/angular-hnxyzs?file=app/app.component.html

Is there any way to force the pipe to be re-applied if the value is updated the the same value?

sdparker
  • 101
  • 2
  • 6
  • the reason is that value doesn't change, so it doesn't format it again, not sure about the solution – Reza Aug 28 '19 at 15:31
  • I think you have to create your own pipe formatter.. – Ronak Patel Aug 28 '19 at 15:33
  • @RonakPatel the issue is not the pipe, it's how angular reports changes on ngModel – Reza Aug 28 '19 at 15:39
  • I actually tried to create my own pipe and set pure to false, which did not work. I agree with @Reza, its related to the fact that angular doesnt think the model is updated, so doesnt re-run the pipe. I am wondering if its possible to add something to (ngModelChange)="testPrice=$event" to manually trigger at re-evaluation – sdparker Aug 28 '19 at 15:45
  • @sdparker `(ngModelChange)` will be fired when model is changed – Reza Aug 28 '19 at 15:47
  • ngModelChange does get fired, and the pipe actually gets evaluated, but the HTML dom element does not get updated. I suppose I could have the ngModelChange call a function that updates the dom element manually, but that seems like overkill – sdparker Aug 28 '19 at 15:56

4 Answers4

1

Create custom pipe and chain with currency pipe.

Try this:

component.html

<input matInput type="text" placeholder="Test Price" [ngModel]="testPrice | mypipe | currency:'USD':'symbol':'2.2'" [ngModelOptions]="{updateOn:'blur'}" 
      (ngModelChange)="testPrice=$event"/>

custom.pipe.ts

import { Pipe, PipeTransform } from '@angular/core';
import { CurrencyPipe } from '@angular/common';
@Pipe({
  name: 'mypipe'
})
export class MypipePipe  extends CurrencyPipe implements PipeTransform {

  transform(value: any, args?: any): any {
    const val = value && value.split('$');
    const trans = val && val[1];
    return trans ? trans.replace(',', '') : value;
  }


}

Example

Chellappan வ
  • 23,645
  • 3
  • 29
  • 60
0

Going through your comments "ngModelChange" not firing or why it's not reformatting. The currency pipe accepts number and does not work if you pass string like $555 or 555,555.

If you type 555555 it turns into $555,555.00 and if you try to remove .00 the value of price is not updated because of the error, passed string to currency pipe. Also, if you remove $ still it does not work as you have , comma and the value of price is not updated.

If you completely remove the value from input box and type new value. Should work fine.

Coming to your case:

Typing 1234 which formats fine but if you delete and put 1234 again it does not reformat. It's because the value of price/ model is not changed. It was 1234 and it is 1234. You just see different formats which does not reflect to your model. After removing 1234 click somewhere to update the price/ model value and type again the same number, and you will notice what's happening.

Since you are using the currency pipe with input and binding model, you have to write a custom pipe or a method to convert your value to currency.

Maihan Nijat
  • 9,054
  • 11
  • 62
  • 110
0

Recalculate the value on blur

Define the following in your html:

<input matInput type="text" placeholder="Test Price" [ngModel]="testPrice | currency:'USD':'symbol':'2.2'" [ngModelOptions]="{updateOn:'blur'}" 
      (ngModelChange)="testPrice=$event" 
      (blur)="onBlurMethod()"/>

Define the following in your component:

  onBlurMethod() {
    this.testPrice = this.currencyPipe.transform(this.testPrice, '2.2')
  }
Miguel Pinto
  • 523
  • 2
  • 8
0

I was able to get this working by running a change detection cycle with a different value.

<input matInput type="text" placeholder="Test Price" [ngModel]="testPrice | currency:'USD':'symbol':'2.2'" [ngModelOptions]="{updateOn:'blur'}" 
  (ngModelChange)="updateModel($event)"/>

Then in TS:

  constructor(private cd: ChangeDetectorRef) { }
  updateModel(event) {
     this.testPrice = null;
     this.cd.detectChanges();
     this.testPrice = event;
  }

I imagine that this would need some extra logic if you had formatting on null.

See example: https://stackblitz.com/edit/angular-6aqm8d?file=app/app.component.html

sdparker
  • 101
  • 2
  • 6