Input validation with pattern Angular 2

52,805

Solution 1

Add the pattern to a variable

var pattern=/06([0-9]{8})/;

and bind the attribute to it

 <input type="text"
               [(ngModel)]="msisdn"
               ngControl="msisdnForm"
               required
               maxlength="10"
               minlength="10"
               [pattern]="pattern"
               #msisdnForm="ngForm"
        >

Seems this PR https://github.com/angular/angular/pull/6623/files needs to land first.

There is still an open issue https://github.com/angular/angular/issues/7595 This prevents pattern being bound to. The pattern needs to be statically added to the DOM (without binding) to work.

Solution 2

I put more details (Angular 2.0.8 - 3 March 2016): https://github.com/angular/angular/commit/38cb526

Example from repo:

<input [ngControl]="fullName" pattern="[a-zA-Z ]*">

I tested it, and it worked :) - here is my code:

<form (ngSubmit)="onSubmit(room)" #roomForm='ngForm'  >
...
<input
  id='room-capacity'
  type="text"
  class="form-control"
  [(ngModel)]='room.capacity'
  ngControl="capacity"
  required
  pattern="[0-9]+"
  #capacity='ngForm'>

UPDATE September 2017

I just wanna to say that currently when I have more experience, I usally use following 'cheap' approach to data validation:

Validation is ONLY on server side (not in angular at all!) and if something is wrong then server (Restful API) return some error code e.g HTTP 400 and following json object in response body (which in angular I put to err variable ):

this.err = { 
    "capacity" : "too_small"
    "filed_name" : "error_name", 
    "field2_name" : "other_error_name",
    ... 
}

(if server return validation error in different format then you can usually easily map it to above structure)

In html template i use separate tag (div/span/small etc.)

<input [(ngModel)]='room.capacity' ...>
<small *ngIf="err.capacity" ...>{{ translate(err.capacity) }}</small>

As you see, when there is some error in 'capacity' then tag with error translation (to user language) will be visible. This approach have following advantages:

  • it is very simple
  • in angular we not double validation code which is (and must be) in server (in case of regexp validation this can either prevent or complicate ReDoS attacks)
  • we have full control on way the error will be shown to user (here as egzample in <small> tag)
  • because in server response we return error_name (instead of direct error message), we can easily change error message (or translate it) by modify only frontend-angular code (or files with translations). So in that case we not need to touch backend/server code.

Of course sometimes (if this is needed - eg. retypePassword field which is never send to server) I make exceptions of above approach and make some validation in angular (but use similar "this.err" mechanism to show errors (so I not use pattern attribute directly in input tag but rather I make regexp validation in some component method after user raise proper event like input-change or save) .

Share:
52,805
Mathijs Segers
Author by

Mathijs Segers

Currently employed as Frontend developer. Background in Mobile, Backend, Frontend with various languages and frameworks.

Updated on July 09, 2022

Comments

  • Mathijs Segers
    Mathijs Segers almost 2 years

    I'm currently writing a simple form in ionic 2 (Angular 2). I was wondering how I'd add a simple regular expression pattern to the validation:

    I basically have this:

    <form>
        <ion-input stacked-label>
            <ion-label>{{label.msisdn}}</ion-label>
            <input type="text"
                   [(ngModel)]="msisdn"
                   ngControl="msisdnForm"
                   required
                   maxlength="10"
                   minlength="10"
                   pattern="06([0-9]{8})"
                   #msisdnForm="ngForm"
            >
        </ion-input>
        <button [disabled]="!msisdnForm.valid" block (click)="requestActivationCode()">
            {{label.requestActivationCode}}
        </button>
    </form>
    

    The maxlength, minlength & required are being picked up (the button is disabled if conditions not met). Now I want to limit the input to numeric and prefix it with 06 (Dutch phone number with minimum amount of numbers).

    The pattern is however not picked up in the validation. Can I do it this way, or do I need a code approach?

  • Mathijs Segers
    Mathijs Segers over 8 years
    So inline won't work, but your suggestion should work in the nearby future?
  • Günter Zöchbauer
    Günter Zöchbauer over 8 years
    You could copy the code from the PR and add them as custom validators until they are included in an official release.
  • Mathijs Segers
    Mathijs Segers about 8 years
    I noticed these things work as well now I'm working on a proper Angular2 Project. It just didn't back then.