Matt
Matt

Reputation: 3716

Angular 5 Validators.pattern regex for only numbers

I'm having trouble getting the Angular 5 Validators.pattern to work. I've tried every regex that SHOULD normally work, but it's not working. I read that Validators.pattern requires a different format, but I can't seem to find it...

Any ideas what the Validators.pattern should be to

(1) allow only numbers, positive and negative

and

(2) allow only numbers, positive and negative, optionally with up to 2 decimal places

Valid examples would be: 1 1.2 1.22 -21 -21.48

Anything with any letter in it would be invalid.

Thanks for your help!

Upvotes: 22

Views: 167343

Answers (6)

Matt Saunders
Matt Saunders

Reputation: 4086

I used the valueChanges property on my fromControl to filter out any non-numeric characters and update its own value, which seems to be a reliable (if over-engineered) solution and avoids having a separate input on the field. But full credit to @Matt for the principle.

This is compatible with the inbuilt Validators.min and Validators.max, but the field in your HTML must have type="text"rather than type="number", otherwise you get some odd behaviour.

myNumberField = new FormControl<number | null>(null);

myNumberFieldSub = this.myNumberField.valueChanges.subscribe(value => {
  let filteredValue = null;
  if (!!value) {
    filteredValue = parseInt(value.toString().replace(/[^0-9]*/, ''));
    if (isNaN(filteredValue)) {
      // Set field back to null if filtered value is not a number
      filteredValue = null;
    }
  }
  this.myNumberField.setValue(filteredValue, { emitEvent: false });
});

Don't forget to unsubscribe!!

Upvotes: 0

Abdus Salam Azad
Abdus Salam Azad

Reputation: 5512

You can try with this regex '^-?[0-9]\d*(\.\d{1,2})?$'. And your form builder will be like below:

this.yourForm= this.formBuilder.group({
    amount: [this.amount, [Validators.required, Validators.pattern('^-?[0-9]\\d*(\\.\\d{1,2})?$')]]
});
 

Upvotes: 3

San Jaisy
San Jaisy

Reputation: 17138

This one work for me in Aungular 7

const numericNumberReg= '^-?[0-9]\\d*(\\.\\d{1,2})?$';

this.$form = this.$builder.group({
      cost: ['', [Validators.required,Validators.pattern(numericNumberReg)]],
    });

Upvotes: 6

Andriy Danylko
Andriy Danylko

Reputation: 139

Allow only integer numbers without symbols.

Validators.pattern(/^[0-9]\d*$/)

Numbers start from one

Validators.min(1)

Upvotes: 13

Yevheniy Potupa
Yevheniy Potupa

Reputation: 577

Don't forget to use with quotes and double backslash in order to make your regex work like it's supposed Validators.pattern('\\-?\\d*\\.?\\d{1,2}') or you can make variable for that

const regexPattern = /\-?\d*\.?\d{1,2}/;
Validators.pattern(regexPattern);

Upvotes: 7

Matt
Matt

Reputation: 3716

After trying so many regex expressions, none was working in Safari. So here's what I did...

First, I used the regex when creating the form control:

new FormControl({value: field.value}, [Validators.required, Validators.pattern(/^-?(0|[1-9]\d*)?$/)])

Then, in the input itself I added an (input) event:

<input matInput (input)="validateInput(field)" [placeholder]="field.label" type="number" [formControlName]="field.id" [id]="field.id">

And that function looks like this:

validateInput(field) {

    this.detailForm.patchValue({ [field.id]: this.detailForm.controls[field.id].value }); }

}

If you enter an invalid character (e.g. a-z) in Safari, it doesn't store it in the field control's value. It only stores valid values (numbers) there. So I'm just patching the value with the stored value -- if it's valid, with numbers, it's fine; if it's invalid, with other characters, then it will replace the input with an empty string.

Works perfectly on all browsers. Hope this helps someone :)

Upvotes: 40

Related Questions