Angular 4 - how to render 2 decimal places for typ

2019-02-19 19:13发布

This question is about restricting/validating the input when the user enters data into an input of type number.

The issue I have is that when the model first loads, any numbers that are integers or 1dp, get rendered with only 1dp. eg 40 or 40.0 both show as 40.0 (not as 40.00).

I have added this code so that after a user types a new value, it shows with 2dp:

in the template file:

(change)="setTwoNumberDecimal($event)"

in the component file:

  setTwoNumberDecimal($event) {
    $event.target.value = parseFloat($event.target.value).toFixed(2);
  }

This works to show 2dp after the user changes the value.

I tried to write a directive that should format to 2dp when the data initially loads, but although the directive does fire, it does not change the value to 2dp.

import { Directive, ElementRef, Input, Renderer2 } from '@angular/core';

@Directive ({
  selector: '[fbDecimalFormat]'
})

export class DecimalFormatDirective {

  constructor(private el: ElementRef,
              private renderer: Renderer2) {
    //renderer.setAttribute(el, 'value', parseFloat(el.nativeElement.value).toFixed(2));
    this.el.nativeElement.value = parseFloat(this.el.nativeElement.value).toFixed(2);
  }

}

FYI the commented render line did not work (error: setAttribute not recognised) - it was an attempt to be platform independent.

So the question is: How can I get the input to render its initial value with 2dps?

2条回答
成全新的幸福
2楼-- · 2019-02-19 19:47

Number.toFixed(x) Formats any number for "x" number of trailing decimals. The number is rounded up, and "0"s are used after the decimal point if needed to create the desired decimal length. In template we can format the value and validating the values

value1 = 0
value2 = 0.0

<p>
  {{value1.toFixed(2)}} - shows 0.00
  {{value2.toFixed(2)}} - shows 0.00
</p>
查看更多
何必那么认真
3楼-- · 2019-02-19 19:49

Template Forms

The solution to this was to use the built-in DecimalPipe (weirdly called number) and not use two-way binding for the model value - ie. from [(ngModel)] to [ngModel] and (ngModelChange)

    <input type="number" step="0.01" 
            (change)="setTwoNumberDecimal($event)"
            (ngModelChange)="item.value=$event"
            [ngModelOptions]="{updateOn: 'blur'}"
            [ngModel]="setting.decimal_value | number:'1.2-2'">

See this question for more info on splitting the [()] binding.

Notice also that the update fires only when the user leaves the control (blur) otherwise every time they type something it will update, which will be a frustrating UX (thanks to @Mihail's comment).

Reactive Forms

In response to the question in the comments: "Could this be used with reactive forms as well?"

The answer is:

No, using pipes with reactive forms is more complicated. You could use the pipe merely to display the value, like

 <p>{{form.get('name').value | myPipe}}</p> 

but I think the correct way is to use value accessor. More info here.

查看更多
登录 后发表回答