Limit input field to two decimal places - Angular 5

白昼怎懂夜的黑 提交于 2019-12-17 11:04:38

问题


The code is as follows

<input type="number" class="form-control" value="" name="cost_price" #name="ngModel" [(ngModel)]="item.cost_price" placeholder="Cost Price"  />

User should not be able to type more that 2 decimal places.

For example, if the user wants to enter 21.256. He should be only allowed to enter 21.25

How to achieve this using angular 5?


回答1:


First create Directive for limit the two decimal places in typescript like this:

import { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({
  selector: '[appTwoDigitDecimaNumber]'
})
export class TwoDigitDecimaNumberDirective {
  private regex: RegExp = new RegExp(/^\d*\.?\d{0,2}$/g);
  private specialKeys: Array<string> = ['Backspace', 'Tab', 'End', 'Home', '-', 'ArrowLeft', 'ArrowRight', 'Del', 'Delete'];
  constructor(private el: ElementRef) {
  }
  @HostListener('keydown', ['$event'])
  onKeyDown(event: KeyboardEvent) {
    console.log(this.el.nativeElement.value);
    // Allow Backspace, tab, end, and home keys
    if (this.specialKeys.indexOf(event.key) !== -1) {
      return;
    }
    let current: string = this.el.nativeElement.value;
    const position = this.el.nativeElement.selectionStart;
    const next: string = [current.slice(0, position), event.key == 'Decimal' ? '.' : event.key, current.slice(position)].join('');
    if (next && !String(next).match(this.regex)) {
      event.preventDefault();
    }
  }
}

Inject Directive in your app.module.ts. In your html use that directive like this:

<input type="textbox" [(ngModel)]="InputValue" appTwoDigitDecimaNumber>

Here is working example in Angular 4/5/6: Limit Two decimal places number validation

Hope this will help you!!!!




回答2:


Answer provided by @Sanoj_V can be improved:

1) you cannot use the arrow keys to edit the number, you can just add digits at the end or you have to click where you want to change the number.

2) once you have two decimals inserted you can only use backspace so either removing the last decimal or clicking somewhere else and removing a digit, but you cannot add anything so you can't change a digit by replacing it.

To solve that just replace : private specialKeys: Array<string> = ['Backspace', 'Tab', 'End', 'Home', '-'];

by: private specialKeys: Array<string> = ['Backspace', 'Tab', 'End', 'Home', '-', 'ArrowLeft', 'ArrowRight'];

Then replace: let next: string = current.concat(event.key);

by: const next: string = [current.slice(0, position), event.key, current.slice(position)].join('');

then add this line just above: const position = this.el.nativeElement.selectionStart;

Thanks @Sanoj_V for this directive, I've spent all day trying to figure out how to deal with currencies input.




回答3:


@Sanoj_v and user3803848 solution works great, but there is one more bug in IE. When user uses dot sign from numeric keyboard, there is emitted 'Decimal' key event and directive not work properly.

Fix for this:

    const next: string = [current.slice(0, position), event.key === 'Decimal' ? '.' : event.key, current.slice(position)].join('');

Just in case, I added '.' and ',' char to regex, that checks user input.

Below whole directive

@Directive({
  selector: '[appTwoDigitDecimalNumber]',
})
export class TwoDigitDecimaNumberDirective {
  private regex: RegExp = new RegExp(/^\d+[.,]?\d{0,2}$/g);// user can put . or , char.
// input also cannot start from , or .
  private specialKeys: Array<string> = ['Backspace', 'Tab', 'End', 'Home', '-', 'ArrowLeft', 'ArrowRight', 'Del', 'Delete'];

  constructor(private el: ElementRef) {
  }

  @HostListener('keydown', ['$event'])
  onKeyDown(event: KeyboardEvent) {
    if (this.specialKeys.includes(event.key)) {
      return;
    }
    const current: string = this.el.nativeElement.value;
    const position = this.el.nativeElement.selectionStart;
    const next: string = [current.slice(0, position), event.key == 'Decimal' ? '.' : event.key, current.slice(position)].join('');
    if (next && !String(next).match(this.regex)) {
      event.preventDefault();
    }
  }
}

You should remember, that is still possible to paste some wrong data into input. That's why, you probably need one more validation, maybe on Input event to prevent pasting wrong data.




回答4:


Easiest way to achieve that would be binding to the "keypress" event and validate with a regex expression whether that's a valid input or not.

<input type="number" ... placeholder="Cost Price"  (keypress)="validateNumber($event)" />

And then the validateNumber would be something like:

validateNumber(e: any) {
    let input = String.fromCharCode(e.charCode);
    const reg = /^\d*(?:[.,]\d{1,2})?$/;

    if (!reg.test(input)) {
      e.preventDefault();
    }
}



回答5:


Maybe you should also look the Form Validation in the Angular guide. It can be useful depending of your form type.




回答6:


I am using ng2-currency-mask, it is pretty useful. it will help you.




回答7:


Below coding is to make textbox to allow numeric field with two decimal places(above two decimal places will give warning),without using regex:

abc.component.html:

<div >
                                <input class="" type="text" [(ngModel)]="" value="" (keyup)="" [disabled]="" (keypress)="numberOnly($event)">
                                <span class="d-block ml-2">NumericBox(two decimal places)</span>
                            </div>

abc.component.ts:

public dotCount:number=0;

numberOnly(event): boolean {          
    const charCode = (event.which) ? event.which : event.keyCode;      
    if (charCode == 46) {
        this.dotCount += 1;
        this.checkNumberOnly = (event.target.value);
        var numericCheck = (event.target.value).toString();
        if (numericCheck.includes('.')) {
            this.dotCount += 1;
        }
        if (this.dotCount > 1) {   
            this.dotCount = 0;
            return false;
        }
    }
    if (charCode > 31 && (charCode < 45 || charCode > 57 || charCode==47)) {
        return false;
    }
    this.checkNumberOnly = (event.target.value);
    if (this.checkNumberOnly != null) {
        var numeric = (event.target.value).toString();
        if (numeric.includes('.')) {
            var checkNumeric = numeric.split('.');
            if (checkNumeric.length > 2) {
                return false;
            }
            this.checkString = checkNumeric[1].split('');
            if (this.checkString.length > 1) {
                this.toastrService.warning("Invalid value", "Warning");
                return false;
            }
        }

    }
    this.dotCount = 0;
    this.cdr.detectChanges();
    return true;

}


来源:https://stackoverflow.com/questions/50722368/limit-input-field-to-two-decimal-places-angular-5

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!