Angular reactive form IP address validator

Viewed 6231

Hellow, i'm try to use a validator for an IP address in angular. However, it seems that even if i inputted an invalid ip address i.e 12.2.2.2..., GUI shows it is valid (see pic). however, console logs shows that it is a pattern mistmatch (this means that it detected an incorrect pattern). I am not sure what i am missing. starting to get confused now. Need a new pair of eyes to spot the defect.

Please note that the required part is already working with ipaddress. I am just confused as to whay it isn't working on pattern validation. See image

enter image description here

See my stackblitz

Here is my code

HTML

<div class="form-group row required" [ngClass]="{
  'is-invalid': ipaddress.invalid && (ipaddress.dirty || ipaddress.touched),
  'is-valid': ipaddress.valid && (ipaddress.dirty || ipaddress.touched)
}">
  <label for="ipaddress" class="col-sm-3 col-form-label">IP Address</label>
  <div class="col-sm-7">
    <input type="text" class="form-control" placeholder="IP Address"
        id="ipaddress" name="ipaddress" formControlName="ipaddress"
        ngbAutofocus required>
    <div class="form-control-feedback invalid-feedback"
        *ngIf="ipaddress.errors">
      <p *ngIf="ipaddress.errors.required">IP Address is required</p>
      <p *ngIf="ipaddress.errors.pattern">Invalid IP Address format</p>
    </div>
  </div>
</div>

TS File

  this.ipaddress = new FormControl('', {
      validators: Validators.compose([
        Validators.required,
        Validators.pattern('(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)')
      ])
    });
2 Answers

I think you have such kind of inconsistency because you're mixing two types of validations that Bootstrap understands:

Client-side validation:

  • requires was-validated class on the <form> tag.

Server-side validation:

  • no need for was-validated class on the tag.
  • requires .is-valid or .is-invalid class on the input control.

You have required attribute on your IP Address input control. This attribute allows browser to apply native built-in form validation, meaning if that control is invalid then it matches the :invalid CSS pseudo-class. Bootstrap framework has dedicated class for this behavior:

.was-validated .form-control:invalid {
  border-color: <red>;
  ...

Since you're also adding was-validated class to the <form> tag it works as you expected.

On the other hand you use Angular validation for pattern:

this.ipaddress = new FormControl('', [
  Validators.required,
  Validators.pattern("....")
]);

It won't apply buil-in browser validation and you have to set .is-valid or .is-invalid manually. But you can use only one type of validation for Bootstrap.

So, here are your options:

  1. Go with client-side validation only:

html

<input type="ipaddress"
    class="form-control"
    formControlName="ipaddress"
    required
    pattern="^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$">

Stackblitz Example

  1. Use Bootstrap server-side validation logic.

To do so

  • you need to remove adding was-validated class to form tag but rather set all current control as touched.

e.g.

this.myform.markAllAsTouched();
  • move adding .is-valid and .is-invalid classes to control itself not to its wrapper

html

<input type="ipaddress"
    class="form-control"
    formControlName="ipaddress"
    [ngClass]="{
  'is-invalid': ipaddress.invalid && (ipaddress.dirty || ipaddress.touched),
  'is-valid': ipaddress.valid && (ipaddress.dirty || ipaddress.touched)
}">

Stackblitz Example

For js & ts you can use the following:

Validators.pattern('(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)')
Related