【问题标题】:limit input type number to 2 place of decimal in angular 2将输入类型号限制为角度 2 中的小数点后 2 位
【发布时间】:2017-06-07 23:09:21
【问题描述】:

我在一个 html 页面上有许多输入框。我想限制用户输入小数点后 2 位之后的任何数字。

目前尝试应用 html 5 输入 Step="0.00" 但不起作用。

任何打字稿解决方案也可以

【问题讨论】:

    标签: validation angular typescript input


    【解决方案1】:

    请参阅Plnkr 中以下指令的演示。

    您可以使用以下指令实现此目的:

    import { Directive, ElementRef, HostListener, Input } from '@angular/core';
    
    @Directive({
      selector: '[OnlyNumber]'
    })
    export class OnlyNumber {
      elemRef: ElementRef
    
      constructor(private el: ElementRef) {
        this.elemRef = el
      }
    
      @Input() OnlyNumber: boolean;
      @Input() DecimalPlaces: string;
      @Input() minValue: string;
      @Input() maxValue: string;
    
      @HostListener('keydown', ['$event']) onKeyDown(event) {
        let e = <KeyboardEvent> event;
        if (this.OnlyNumber) {
          if ([46, 8, 9, 27, 13, 110, 190].indexOf(e.keyCode) !== -1 ||
            // Allow: Ctrl+A
            (e.keyCode == 65 && e.ctrlKey === true) ||
            // Allow: Ctrl+C
            (e.keyCode == 67 && e.ctrlKey === true) ||
            // Allow: Ctrl+X
            (e.keyCode == 88 && e.ctrlKey === true) ||
            // Allow: home, end, left, right
            (e.keyCode >= 35 && e.keyCode <= 39)) {
              // let it happen, don't do anything
              return;
            }
            // Ensure that it is a number and stop the keypress
            if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
                e.preventDefault();
            }
          }
      }
    
      @HostListener('keypress', ['$event']) onKeyPress(event) {
        let e = <any> event
    
        let valInFloat: number = parseFloat(e.target.value)
    
        if(this.minValue.length) {
          // (isNaN(valInFloat) && e.key === "0") - When user enters value for first time valInFloat will be NaN, e.key condition is 
          // because I didn't want user to enter anything below 1.
          // NOTE: You might want to remove it if you want to accept 0
          if( valInFloat < parseFloat(this.minValue) || (isNaN(valInFloat) && e.key === "0") ) {
            e.preventDefault();
          }
        }
    
        if(this.maxValue.length) {
          if(valInFloat > parseFloat(this.maxValue)) {
            e.preventDefault();
          }
        }
    
        if (this.DecimalPlaces) {
          let currentCursorPos: number = -1;    
          if (typeof this.elemRef.nativeElement.selectionStart == "number") {
              currentCursorPos = this.elemRef.nativeElement.selectionStart;
          } else {
            // Probably an old IE browser 
            console.log("This browser doesn't support selectionStart");
          }
    
          let dotLength: number = e.target.value.replace(/[^\.]/g, '').length
          // If user has not entered a dot(.) e.target.value.split(".")[1] will be undefined
          let decimalLength = e.target.value.split(".")[1] ? e.target.value.split(".")[1].length : 0;
    
          // (this.DecimalPlaces - 1) because we don't get decimalLength including currently pressed character 
          // currentCursorPos > e.target.value.indexOf(".") because we must allow user's to enter value before dot(.)
          // Checking Backspace etc.. keys because firefox doesn't pressing them while chrome does by default
          if( dotLength > 1 || (dotLength === 1 && e.key === ".") || (decimalLength > (parseInt(this.DecimalPlaces) - 1) && 
            currentCursorPos > e.target.value.indexOf(".")) && ["Backspace", "ArrowLeft", "ArrowRight"].indexOf(e.key) === -1 ) {
            e.preventDefault();
          }
        }  
      }
    }
    

    HTML用法如下:

    <input type="text" OnlyNumber="true" DecimalPlaces="2" minValue="1.00" maxValue="999999999.00">
    

    如果您发现任何错误,请在下面的 cmets 中告诉我。

    P.S:这个指令是对 answer 的改进工作,以验证小数点。

    【讨论】:

    • 在 Chrome(版本 58.0.3029.110)上,Angular 2.4.0 - 小数位检查不起作用(this.elemRef.nativeElement.selectionStart 为空)。但否则真的很整洁。
    • 谢谢。我在 OS X El Capitan 上使用 Angular 4.0.0 和 chrome 57.0.2987.133(64 位)。我修复了一个 Firefox 错误,现在它也可以在 Firefox v53 上运行。如果您找到解决方法,请随时提出修改建议
    • @Dhyey 如果您输入小数点数字并选择或突出显示小数点后的最后一位数字并尝试将其替换为另一个数字,它将不起作用。
    • 我在angularJS中写了一个类似的指令,并写了这个函数来获取光标位置作为跨浏览器的解决方案。到目前为止它对我有用:var getCursorPosition = function (elem) { var pos = 0; if (document.selection) { elem.focus(); var sel = document.selection.createRange(); sel.moveStart('character', -elem.value.length); pos = sel.text.length; } else if (elem.selectionStart || elem.selectionStart == '0') { pos = elem.selectionStart; } return pos; }; 抱歉,这种格式看起来很奇怪。评论不会保留其格式。
    【解决方案2】:

    我使用@pipe 得到了解决方案

    import { Directive,Input,Inject, HostListener, ElementRef, OnInit } from "@angular/core";
    
    
    const PADDING = "000000";
    
    @Pipe({ name: "CurrencyPipe" })
    export class CurrencyPipe implements PipeTransform {
      transform(value: any, args: string[]): any {
         var clean = value.replace(/[^-0-9\.]/g, '');
        var negativeCheck = clean.split('-');
        var decimalCheck = clean.split('.');
    
         if (negativeCheck[1] != undefined) {
                            negativeCheck[1] = negativeCheck[1].slice(0, negativeCheck[1].length);
                            clean = negativeCheck[0] + '-' + negativeCheck[1];
                            if (negativeCheck[0].length > 0) {
                                clean = negativeCheck[0];
                            }
    
                        }
            if (decimalCheck[1] != undefined) {
                            decimalCheck[1] = decimalCheck[1].slice(0, 2);
                            clean = decimalCheck[0] + '.' + decimalCheck[1];
                        }
    
        return clean;
      }
    
      parse(value: string, fractionSize: number = 2): string {
    
         var clean = value.replace(/[^-0-9\.]/g, '');
        var negativeCheck = clean.split('-');
        var decimalCheck = clean.split('.');
    
         if (negativeCheck[1] != undefined) {
                            negativeCheck[1] = negativeCheck[1].slice(0, negativeCheck[1].length);
                            clean = negativeCheck[0] + '-' + negativeCheck[1];
                            if (negativeCheck[0].length > 0) {
                                clean = negativeCheck[0];
                            }
    
                        }
            if (decimalCheck[1] != undefined) {
                            decimalCheck[1] = decimalCheck[1].slice(0, 2);
                            clean = decimalCheck[0] + '.' + decimalCheck[1];
                        }
    
        return clean;
      }
    
    }
    

    管道在我的指令中扩展。

    import { Directive, Input, Inject, HostListener, OnChanges, ElementRef, Renderer, AfterViewInit, OnInit } from "@angular/core";
    import { CurrencyPipe } from '../../shared/pipe/orderby';
    
    @Directive({ selector: "[CurrencyFormatter]" })
    export class CurrencyFormatterDirective {
    
      private el: HTMLInputElement;
    
      constructor(
        private elementRef: ElementRef,
        private currencyPipe: CurrencyPipe
      ) {
        this.el = this.elementRef.nativeElement;
      }
    
      ngOnInit() {
        this.el.value = this.currencyPipe.parse(this.el.value);
      }
    
      @HostListener("focus", ["$event.target.value"])
      onFocus(value) {
        this.el.value = this.currencyPipe.parse(value); // opossite of transform
      }
    
      @HostListener("blur", ["$event.target.value"])
      onBlur(value) {
        this.el.value = this.currencyPipe.parse(value);
      }
    
      @HostListener("keyup", ["$event.target.value"]) 
      onKeyUp(value) {
        this.el.value = this.currencyPipe.parse(value);
      }
    
    
    
    }
    

    在您的组件上导入指令

    import { CurrencyFormatterDirective } from '../../shared/directive/showOnRowHover';
    import { CurrencyPipe } from '../../shared/pipe/orderby';
    providers: [CurrencyPipe,
              CurrencyFormatterDirective]
    

    您的 html 输入指令

     <input type="text"  [(ngModel)]="invoiceDetail.InvoiceAmount" class="form-control"  placeholder="Enter invoice amount"
              CurrencyFormatter>
    

    【讨论】:

    • 这很好用,但我必须从核心导入 PipeTransform,并将管道作为提供程序添加到指令中以使其注入,并将其添加到我的模块声明中
    【解决方案3】:
    <input type='number' step='0.01' value='0.00' placeholder='0.00' />
    

    不要使用Step 使用step,如果你仍然想要旧浏览器的支持,你可以选择相同的javascript代码

    【讨论】:

    • 不限制用户输入超过 2 位小数。
    猜你喜欢
    • 2023-04-02
    • 2021-10-29
    • 1970-01-01
    • 1970-01-01
    • 2020-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多