Format input value using [ngModel] and (ngModelChange) while typing

Asked

Viewed 846 times

1

I ran it through the OR and PTSD to see if anyone else had the same thing, but I don’t think so. I have an app with a input so that a certain value is typed and formatted at the same time, as follows:

<input matInput placeholder="Proposta" #valorPropostaInput [ngModel]="valorProposta" (ngModelChange)="valorProposta = FormatarValorExibicao(valorPropostaInput.value)">

In my file .ts, the function FormatarValorExibicao returns the formatted value for Brazilian currency:

valorProposta: string = '';

FormatarValorExibicao(valor)
{
    const v = ((valor.replace(/\D/g, '') / 100).toFixed(2) + '').split('.');

    const m = v[0].split('').reverse().join('').match(/.{1,3}/g);

    for (let i = 0; i < m.length; i++)
        m[i] = m[i].split('').reverse().join('') + '.';

    const r = m.reverse().join('');

    return [r.substring(0, r.lastIndexOf('.')), ',', v[1]].join('');
}

The above function works correctly. The problem is when I type letters instead of numbers. I checked that by putting console.log for the return of the method, the value is formatted correctly, but the view simply does not update the value with [ngModel].

To the input with value of 12345:

  • The value formatted by the function is 123,45 (correct);
  • If I put a text character (123,45a or 123,45abcd), the value returned by the function is the same (123,45 - correct), but the view is not updated with the return. The value displayed in input stays (123,45a or 123,45abcd);
  • If in the input is 123,45a or 123,45abcd and I enter any number (6), the view is updated and the expected behavior happens (1.234,56) for both cases.

I have tried to pass as a parameter the $event for the above function, but unsuccessfully:

<input matInput placeholder="Proposta" [ngModel]="valorProposta" (ngModelChange)="valorProposta = FormatarValorExibicao($event)">

If I modify the (ngModelChange) to just call the method FormatarValorExibicao passing the $event or the property value of input and then within the method do not return the value, but assign the variable valorProposta the expected, it gives in the same. The view is not updated, i.e.:

<input matInput placeholder="Proposta" #valorPropostaInput [ngModel]="valorProposta" (ngModelChange)="FormatarValorExibicao(valorPropostaInput.value)">
<input matInput placeholder="Proposta" [ngModel]="valorProposta" (ngModelChange)="FormatarValorExibicao($event)">

And then:

FormatarValorExibicao(valor)
{
    const v = ((valor.replace(/\D/g, '') / 100).toFixed(2) + '').split('.');

    const m = v[0].split('').reverse().join('').match(/.{1,3}/g);

    for (let i = 0; i < m.length; i++)
        m[i] = m[i].split('').reverse().join('') + '.';

    const r = m.reverse().join('');

    this.valorProposta = [r.substring(0, r.lastIndexOf('.')), ',', v[1]].join('');
}

I believe the mistake is not in RegEx, because I tested many times on the site Online Javascript Editor, but I could be wrong. I even tried to add the property name="algumaCoisa" at the input, but it made no difference. The view not being updated just when typing letters is really weird, I don’t know how to get around it or if I’m using the [ngModel] and the (ngModelChange) incorrectly.

Thank you.

  • 1

    I think I’d better use some mask library or something

1 answer

1


The solution would be to change the event and use the Two-way Data-Binding, see the section Binding syntax: an Overview.

<input matInput placeholder="Proposta" [(ngModel)]="valorProposta" (keyup)="FormatarValorExibicao($event)" >

File . ts:

//...
public valorProposta: any;

public FormatarValorExibicao($event): void {
   let valor = this.valorProposta;
   const v = ((valor.replace(/\D/g, '') / 100).toFixed(2) + '').split('.');
   const m = v[0].split('').reverse().join('').match(/.{1,3}/g);

   for (let i = 0; i < m.length; i++)
       m[i] = m[i].split('').reverse().join('') + '.';

   const r = m.reverse().join('');
   this.valorProposta = [r.substring(0, r.lastIndexOf('.')), ',', v[1]].join('');
}

In the meantime there are libraries that already solve the problem, for example, ngx-Mask.

  • Thank you, Filipe. Your solution really worked. I just had to initialize the variable valorPorposta with ''.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.