Angular 4 Form Validators - minLength & maxLength does not work on field type number
Asked Answered
A

14

59

I am trying to develop a contact form, I want user to enter phone number values between length 10-12.

Notably same validation is working on Message field, Its only number field which is giving me trouble.

I found this answer but it is of no use for me.

I have code like following :

HTML :

<form [formGroup]="myForm" (ngSubmit)="myFormSubmit()">
      <input type="number" formControlName="phone" placeholder="Phone Number">
      <input type="text" formControlName="message" placeholder="Message">
       <button class="button" type="submit" [disabled]="!myForm.valid">Submit</button>
</form>

TS :

this.myForm = this.formBuilder.group({
     phone: ['',  [Validators.required, Validators.minLength(10), Validators.maxLength(12)]],
     message: ['',  [Validators.required, Validators.minLength(10), Validators.maxLength(100)]]
});`
Abscind answered 9/9, 2017 at 10:31 Comment(6)
Numbers don't have length as far as form validation is concerned. If you want 10-12 digits, what you really want is numbers between 1,000,000,000 and 1,000,000,000,000, surely?Tamah
Yes, I need numbers between 10000000000 to 999999999999Abscind
Then use that, rather than trying to check the length.Tamah
So there is no default method for that? we'll have to create one to limit those?Abscind
What makes you say that? See angular.io/api/forms/Validators, which shows both min and max.Tamah
Thanks, My mistake, Just saw it, wrote it, and it worked. :)Abscind
A
34

Used it like following and worked perfectly :

phone: ['',  [Validators.required, Validators.min(10000000000), Validators.max(999999999999)]],

customValidationService :

import { AbstractControl, ValidatorFn } from '@angular/forms';

export class customValidationService {
   static checkLimit(min: number, max: number): ValidatorFn {
    return (c: AbstractControl): { [key: string]: boolean } | null => {
        if (c.value && (isNaN(c.value) || c.value < min || c.value > max)) {
            return { 'range': true };
        }
        return null;
    };
  }
}
Abscind answered 9/9, 2017 at 11:2 Comment(2)
I know I'm a year late here, and it's not exactly what was asked in the OP, but nobody will want to enter a phone number as <input type='number'>. The answer under "Update 1" is correct for integers, but a phone number is not an integer. This isn't even the "falsehoods about phone numbers" piece I was looking for, but it has a lot of good points.Mover
But with this soution you can add zeros on the left withour being controlled , maxlength(10) and max(999999999) are not the same -_-Georgeannageorgeanne
P
19

try this working sample code :

component.html

<div class="container">
    <form [formGroup]="myForm" 
    (ngFormSubmit)="registerUser(myForm.value)" novalidate>
        <div class="form-group" [ngClass]="{'has-error':!myForm.controls['phone'].valid}">
            <label for="phone">Email</label>
            <input type="phone" formControlName="phone" placeholder="Enter Phone" 
            class="form-control">
            <p class="alert alert-danger" *ngIf="myForm.controls['phone'].hasError('minlength')">
                Your phone must be at least 5 characters long.
            </p>
            <p class="alert alert-danger" *ngIf="myForm.controls['phone'].hasError('maxlength')">
                Your phone cannot exceed 10 characters.
            </p>
            <p class="alert alert-danger" *ngIf="myForm.controls['phone'].hasError('required') && myForm.controls['phone'].dirty">
                phone is required
            </p>
        </div>
        <div class="form-group text-center">
            <button type="submit" class="btn btn-primary" [disabled]="!myForm.valid">Submit</button>
        </div>
    </form>
</div>

component.ts

import { FormGroup, FormBuilder, Validators } from '@angular/forms';

export class AppComponent implements OnInit {
    myForm: any;
    constructor(private formBuilder: FormBuilder) { }
    
    ngOnInit() {
        this.myForm = this.formBuilder.group({
            phone: [null, Validators.compose([Validators.required, Validators.minLength(5), Validators.maxLength(10)])]
        });
    }
}
Putout answered 9/9, 2017 at 11:14 Comment(0)
R
16

I have a trick that 100% work.

Define input of type 'text' and not 'number'.

For eg:

<input placeholder="OTP" formControlName="OtpUserInput" type="text">

Then use pattern which is part of Validation.

Like :

this.ValidOtpForm = this.formbuilder.group({
             OtpUserInput: new FormControl(
              { value:'', disabled: false },
          [
          Validators.required,
          Validators.minLength(6),
          Validators.pattern('[0-9]')
        ]),
});

It means we define input type text that is suitable for min length and we also define pattern(validation) for numeric value so that we can achieve both validation.

Remaining code :

<mat-error *ngIf="RegistrationForm.controls['Password'].hasError('minlength')">Use 6 or more characters with a mix of letters</mat-error>
<mat-error *ngIf="ValidOtpForm.controls['OtpUserInput'].hasError('pattern')">Please enter numeric value.</mat-error>
Robeson answered 4/1, 2019 at 11:7 Comment(1)
Excellent worked perfect for me. A small detail is that when we declare minlength in the mat-error note that it is lowercase, while in the validator it is minLength with uppercase.Ego
B
8

You should not use length here, for min and max use custom validator like this,

var numberControl = new FormControl("", CustomValidators.number({min: 10000000000, max: 999999999999 }))

Angular2 min/max validators

Bogan answered 9/9, 2017 at 10:46 Comment(0)
C
5

This trick will be helpful

In .html file

 <input type="text" (keyup)="onKeyUp($event)" formControlName="phone" placeholder="Phone Number">

In .ts file

The below code restrict string characters

    public onKeyUp(event: any) {
    const NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
    let newValue = event.target.value;
    let regExp = new RegExp(NUMBER_REGEXP);

    if (!regExp.test(newValue)) {
      event.target.value = newValue.slice(0, -1);
    }
   }

and other validation

phone: ['', Validators.compose([
        Validators.required, 
         Validators.pattern('^[0-9]{0,30}$')])
      ])],

The above pattern code allow number upto 30 digits. If you want minimum two digits, you can do like this

 Validators.pattern('^[0-9]{2,30}$')
Crimson answered 6/4, 2020 at 8:22 Comment(5)
Why use extra event keyup when Angular can do it without it?Abscind
I added keyup event to remove special characters or operators while entering otherwise its up to you to add keyup event or notCrimson
Using type="number" removes special characters, doesn't it?Abscind
Yes it removes special characters in type= number but it will have + , - , e while entering . If you want to restrict these operators while entering use keyup event else everything is fine.Crimson
I only had to use other validation section.Ligulate
H
3

You can use a pattern instead to validate your phone number, and change your input type to text

<input type="text" formControlName="phone" placeholder="Phone Number">

and use this pattern for phone number tha have a length between 10 and 12

phonePattern = /^[0-9]{10,12}$/;

and change the validator on your form control

phone: ['',  [Validators.required, Validators.pattern(this.phonePattern)]],

and you can display the error:

<div *ngIf="myForm.get('phone').invalid">
      <div class="error-message invalid-feedback" *ngIf="myForm.get('phone').hasError('required')">
        required!
      </div>
      <div class="error-message invalid-feedback" *ngIf="myForm.get('phone').hasError('pattern')">
        invalid!
      </div>
</div>
Hacking answered 17/6, 2020 at 15:49 Comment(0)
M
1

The Form Validation of multiple parameters or multiple conditions should be composed as single validator otherwise you will get observable or promise error:

phone: ['',  Validators.compose([Validators.required,Validators.min(10000000000), Validators.max(999999999999)])],
Mckale answered 30/9, 2018 at 14:26 Comment(0)
V
0

For a number field, you can validate min and max values using built in Angular validation, like this:

.ts

import { FormBuilder, FormGroup, Validators } from '@angular/forms';

private myNumberFieldMin: number = 1;
private myNumberFieldMax: number = 1000000;

constructor() {
      this.myForm = this.formBuilder.group({
        myNumberField
      })

this.myForm.controls.myNumberField.setValidators([
  Validators.min(this.myNumberFieldMin),
  Validators.max(this.myNumberFieldMax)
]);

html

<form [formGroup]="myForm">
  <input type="number" formControlName="myNumberField">

  <div *ngIf="this.myForm.controls['myNumberField'].errors && this.myForm.controls['myNumberField'].errors.min">
    <span class="error-message">Value must be at least {{myNumberFieldMin}}</span>
  </div>
  <div *ngIf="this.myForm.controls['myNumberField'].errors && this.myForm.controls['myNumberField'].errors.max">
    <span class="error-message">Maximum value is {{myNumberFieldMax}}</span>
  </div>
</form>
Vinegarette answered 26/9, 2018 at 1:17 Comment(0)
P
0

Keep <input type="number" /> and just transform the int values to strings.

const phoneControl: FormControl = this.myForm.controls.phone;

// Do not forget to unsubscribe

phoneControl.valueChanges.subscribe(v => {

  // When erasing the input field, cannot read toString() of null, can occur
  phoneControl.setValue((v && v.toString()) || null, { emitEvent: false });
});
Palermo answered 28/6, 2019 at 14:14 Comment(0)
G
0
<mat-error>
   <span *ngIf="phone.errors?.required">campo obrigatório</span>
   <span *ngIf="phone.errors?.minlength">o nº deve conter no mínimo 13 dígitos</span>
   <span *ngIf="phone.errors?.maxlength">o nº deve conter no máximo 13 dígitos</span>
</mat-error>
Gregor answered 16/12, 2022 at 20:44 Comment(0)
U
0

In my case I used maxLength instead of maxlength (notice the lowercase l ) in the template.

Uttermost answered 13/8, 2023 at 10:24 Comment(0)
M
-1
<div nz-col [nzXs]="24" [nzSm]="12" nz-form-control nzHasFeedback>
                                <nz-input formControlName="password" [nzPlaceHolder]="'password'" [nzType]="'password'" [nzSize]="'large'" (ngModelChange)="validateConfirmPassword()">
                                </nz-input>
                                <div nz-form-explain *ngIf="getFormControl('password').dirty&&getFormControl('password').hasError('minlength')">Your password must be at least 5 characters long. </div>
                                <div nz-form-explain *ngIf="getFormControl('password').dirty&&getFormControl('password').hasError('maxlength')">Your password cannot exceed 15 characters. </div>
                                <div nz-form-explain *ngIf="getFormControl('password').dirty&&getFormControl('password').hasError('required')">Please input your password!</div>
                            </div>
Maxim answered 23/4, 2018 at 11:14 Comment(2)
Ts File import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; @Component({ selector: 'ftl-signup', templateUrl: './signup.component.html', styleUrls: ['./signup.component.scss'] }) export class PasswordChecker implements OnInit { validateForm: FormGroup; constructor(private fb: FormBuilder) { password: ['', [Validators.required, Validators.minLength(5), Validators.maxLength(15)]], }); }Maxim
You should edit your answer instead of adding comments to your own answer.Savoyard
A
-1

If you want to validate a field by multiple validators then, You should try this

phone: ['', Validators.compose([
        Validators.required, 
        Validators.minLength(10),
        Validators.maxLength(12)])
      ])],
Azerbaijan answered 8/12, 2018 at 14:56 Comment(0)
F
-2

Use Compose() method, compose multiple validators into a single function.

Update .TS file as below,

this.myForm = this.formBuilder.group({ phone: ['', Validators.compose([Validators.required, Validators.minLength(10), Validators.maxLength(12)])], message: ['', Validators.compose([Validators.required, Validators.minLength(10), Validators.maxLength(100)])] });

Freytag answered 16/10, 2018 at 9:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.