And initialized here:
 
this.authForm = fb.group({  
    'username': ['', Validators.compose([Validators.required, Validators.minLength(8), CustomValidators.checkFirstCharacterValidator])],
    'password': ['', Validators.compose([Validators.required, Validators.minLength(8), CustomValidators.checkFirstCharacterValidator])]
});
 
So we’re using FormBuilder helper service fb to group form fields into ControlGroup object called authForm.
 
I hope all this makes sense. It’s almost funny, but validation is the easiest part here. 🙂
 
Everything said here makes an Angular2 form, but what about validation?
 
Let’s once again take a look at these lines:
 
'username': ['', Validators.compose([Validators.required, Validators.minLength(8), CustomValidators.checkFirstCharacterValidator])],
'password': ['', Validators.compose([Validators.required, Validators.minLength(8), CustomValidators.checkFirstCharacterValidator])]
 
We have defined three validation rules for each form filed. First two rules are predefined with Angular2, required and minLength.
 
On the other hand, a third one is a custom made validation. It’s called checkFirstCharacterValidator, and it’s pointing to an identically named function which can be found in another class called CustomValidators.ts.
 
public static checkFirstCharacterValidator(control: Control): ValidationResult {
    var valid = /^\d/.test(control.value);
    if (valid) {
        return {checkFirstCharacterValidator: true};
    }
    return null;
}
 
Now let’s take a look how everything looks like from an HTML point of view:
 
<ion-item [class.error]="!password.valid && password.touched">
    <ion-label floating>Password</ion-label>
    <ion-input type="text" value="" [ngFormControl]="password" ></ion-input>
</ion-item>
<div *ngIf="password.hasError('required') && password.touched" 
    class="error-box">* Password is required</div>    
<div *ngIf="password.hasError('minlength') && password.touched" 
    class="error-box">* Minimum password length is 8!</div>                     
<div *ngIf="password.hasError('checkFirstCharacterValidator') && password.touched" 
    class="error-box">* Password cant't start with number!</div>    
 
In case, a password is not valid (!password.valid) after a field has been touched (password.touched) Angular2 will add a class error to ion-input element:
 
<ion-item [class.error]="!password.valid && password.touched">
 
password keyword here is a reference to password Control object.
 
At the same time, below each field, we can find three additional div elements holding error descriptions. In case fields (username or password) have validation errors, a related description will become visible.
 
<div *ngIf="password.hasError('required') && password.touched" 
    class="error-box">* Password is required</div>    
<div *ngIf="password.hasError('minlength') && password.touched" 
    class="error-box">* Minimum password length is 8!</div>                     
<div *ngIf="password.hasError('checkFirstCharacterValidator') && password.touched" 
    class="error-box">* Password cant't start with number!</div> 
 
Finally, if everything is OK and application form is successfully validated, we’ll enable submit button:
 
<button type="submit" class="custom-button" [disabled]="!authForm.valid" block>Submit</button>
 

Code

 
Update: 28.06.2016 (July 28th) - Article and example are updated to match changes made to Ionic 2.0.0-beta.10 version
 
In case GitHub repo is not available and you can only use code provided below, this is what project folder looks like (image was taken from the Sublime text editor):
 
Ionic 2 Form Validation Folder Structure
 
index.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
  <title>Ionic</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-eval' 'unsafe-inline' *; object-src 'self'; style-src 'self' 'unsafe-inline'; media-src *">
  <meta name="format-detection" content="telephone=no">
  <meta name="msapplication-tap-highlight" content="no">

  <link ios-href="build/css/app.ios.css" rel="stylesheet">
  <link md-href="build/css/app.md.css" rel="stylesheet">
  <link wp-href="build/css/app.wp.css" rel="stylesheet">
</head>

<body>
  <ion-app></ion-app>

  <!-- cordova.js required for cordova apps -->
  <script src="cordova.js"></script>
  <!-- Polyfill needed for platforms without Promise and Collection support -->
  <script src="build/js/es6-shim.min.js"></script>
  <!-- Zone.js and Reflect-metadata  -->
  <script src="build/js/Reflect.js"></script>
  <script src="build/js/zone.js"></script>
  <!-- the bundle which is built from the app's source code -->
  <script src="build/js/app.bundle.js"></script>
</body>

</html>
 
app.html
<ion-nav [root]="rootPage"></ion-nav>
 
app.ts
import {Component} from '@angular/core';
import {Platform, ionicBootstrap} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {FormPage} from './pages/form/form';


@Component({
  templateUrl: 'build/app.html',
})

export class MyApp {
  rootPage: any = FormPage;

  constructor(platform: Platform) {
    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      StatusBar.styleDefault();
    });
  }
}

ionicBootstrap(MyApp);
 
form.html
<ion-header>
	<ion-navbar>
		<ion-title>
			Authorization Form Demo
		</ion-title>
	</ion-navbar>
</ion-header>

<ion-content class="home" padding>
    <form [ngFormModel]="authForm" (ngSubmit)="onSubmit(authForm.value)">
        <ion-item [class.error]="!username.valid && username.touched">
            <ion-label floating>Username</ion-label>
            <ion-input type="text" value="" [ngFormControl]="username"></ion-input>         
        </ion-item>
        <div *ngIf="username.hasError('required') && username.touched" 
            class="error-box">* Username is required!</div>
        <div *ngIf="username.hasError('minlength') && username.touched" 
            class="error-box">* Minimum username length is 8!</div>            
        <div *ngIf="username.hasError('checkFirstCharacterValidator') && username.touched" 
            class="error-box">* Username cant't start with number!</div>                       
        <ion-item [class.error]="!password.valid && password.touched">
            <ion-label floating>Password</ion-label>
            <ion-input type="text" value="" [ngFormControl]="password" ></ion-input>
        </ion-item>
        <div *ngIf="password.hasError('required') && password.touched" 
            class="error-box">* Password is required</div>    
        <div *ngIf="password.hasError('minlength') && password.touched" 
            class="error-box">* Minimum password length is 8!</div>                     
        <div *ngIf="password.hasError('checkFirstCharacterValidator') && password.touched" 
            class="error-box">* Password cant't start with number!</div>             
        <br/><br/> 
        <button type="submit" class="custom-button" [disabled]="!authForm.valid" block>Submit</button>
    </form>
</ion-content>
 
form.ts
import {Component} from '@angular/core';
import {NavController} from 'ionic-angular';
import {FORM_DIRECTIVES, FormBuilder,  ControlGroup, Validators, AbstractControl} from '@angular/common';
import {CustomValidators} from '../validators/CustomValidators';


@Component({
    templateUrl: 'build/pages/form/form.html',
	directives: [FORM_DIRECTIVES]
})

export class FormPage {

    authForm: ControlGroup;
    username: AbstractControl;
    password: AbstractControl;

    constructor(private navController: NavController, private fb: FormBuilder) {
        this.authForm = fb.group({  
            'username': ['', Validators.compose([Validators.required, Validators.minLength(8), CustomValidators.checkFirstCharacterValidator])],
            'password': ['', Validators.compose([Validators.required, Validators.minLength(8), CustomValidators.checkFirstCharacterValidator])]
        });
 
        this.username = this.authForm.controls['username'];     
        this.password = this.authForm.controls['password'];  
    }
	
    onSubmit(value: string): void { 
        if(this.authForm.valid) {
            console.log('Submitted value: ', value);
        }
    } 	
}
 
CustomValidators.ts
import { Control, ControlGroup } from "@angular/common";

interface ValidationResult {
    [key: string]: boolean;
}

export class CustomValidators {

    public static checkFirstCharacterValidator(control: Control): ValidationResult {
        var valid = /^\d/.test(control.value);
        if (valid) {
            return {checkFirstCharacterValidator: true};
        }
        return null;
    }
}
 

Deployment

 
Next step, build our application:
 
ionic build android
 
Be careful here, this step may break if you’re behind a firewall. The first execution will take a long time, so be patient.
 
Finally:
 
ionic run android -l -c -s
 
or if you want to see it inside a browser:
 
ionic run android -l -c -s
 

Download The Code

 
Working GitHub repo link can be found below:
 
GitHub
 
 

What to read next

IONIC 2 | How To Work with Cordova Plugins
 
 

Who Am I?

Between working as a senior Java developer in one of the largest insurance companies in the world and traveling, in my free time, I work as a professional mobile development adviser. I'm also a major jQuery Mobile supporter back at StackOverflow and a forum moderator at the official Ionic Framework forum.

Blogs worth reading

If you're here looking for information related to the Ionic Framework, you will also like these blogs:






  • Works great 🙂 Thank you for sharing it. Though, I did not try custom method for validating.

    • You’re welcome … neighbour 🙂

    • karthiikk Baleneni

      whether its working in latest ionic2 beta v0.0.25

  • Thanks for that. It would be helpful to state what files these code blocks go into..

  • Thanks for that. This helped me a lot.

    I managed to get rid of the ‘function’ keyword in
    checkFirstCharacterValidator(control: Control): { [s: string]: boolean } { … }

    by adding ‘this’ in the Validators group:
    ‘username’: [”, Validators.compose([Validators.required, Validators.minLength(8), this.checkFirstCharacterValidator])],

    I also didn’t need to add the class declarations as they are already declared in the constructor:
    //authForm: ControlGroup;
    //username: AbstractControl;
    //password: AbstractControl;

    Lastly I changed the return line from the checkFirstCharacterValidator function to:
    return {“invalid_firstCharacter”: true};
    as I found naming the string and the method the same confusing (even though that’s what the native angular 2 validator functions do).

  • aluknot

    One of the things i don’t like about ionic 2 is the import part… you need to import a lot of things, when you only want to do something really simple. How can i remember this? i have to come back to this article every time.

  • Graciele E. Victor

    I’d love to see this article updated to Ionic 2 beta 6

  • karthiikk Baleneni

    whether it will work in Ioinic 2 @beta 0.25?? seems to be its not working.

  • Cyril Zilbermann

    Hi,
    Thanks for your share !
    I’m very newbie on ionic.
    However, I’ve a trouble : I’ve copy/paste your code for testing and I’ve compilation parsing error on three variables declaration (authForm, username and password).
    It seems does not accept variable declaration on class and I don’t know why.
    Could you help me ?
    Thanks

    • Cyril Zilbermann

      Sorry,
      My bad, i tried to work a TS code like a JS one :/
      Works perfectly !
      Thanks !

  • Varshil Shah

    hi i used your code AND ITS’S RUN PERFECT BUT PROBLEM IS THAT I WANT USERNAME AND PASSWORD IN STRING VARIABLE . I DON’T KNOW HOW I DO THAT

    • Don’t forget that this is still JavaScript and that every object is easily readable.

      For example, you can use this:

      console.log(this.username);

      To find out what AbstractControl object looks like. And it will tell you that value is accessible like this:

      console.log(this.username.value);
      console.log(this.password.value);

      • Varshil Shah

        thanx..solved problem

        • Your welcome

          • Varshil Shah

            Hey I have one another problem..I getting the response from the server now it’s not fully json response so I want cut string how I do it in ionic 2..

          • My advice, Google it

          • Varshil Shah

            i already do it but i didn’t anything find it.

  • Davide Troise

    HI! I’m trying to follow your guide, but there’s no way i can make the custom Validator Work :/
    I wrote a console.log() in the validator, but it never appears, like it’s never called! Would you please paste your whole CustomValidator.ts file? Thanks!

    • Just download my GitHub example, you can find it on the second page. Though I will also add CustomValidator.ts, I forgot to add it after my last article update.

      • Andre Dreyer

        After having a look at the required validator I realised that the logic of the custom validator function had to be inverted. If (valid) return null else return {‘required’: true}

    • I have update article with CustomValidators.ts class example

  • Palmani

    Hi, Thanks for your post. It’s really helped a lot. Please help me to add validation for creating dynamic elements. i’m trying to add validation for input elements using ng-repeat.

  • Áron Barócsi

    is this is depreciated as of rc4?

    • James Trigg

      Yes think so. beta11 is now using the new angular forms.
      think you use some setting in ionicBootstrap to use the old forms but not really the way forward.

  • james stevens

    hey i am not able to submit the form,when i click on submit there is no submitted values shown in the console

  • manoj meshram

    hi, There is any way to submit image with form’s other field?

  • Lokesh Sahu

    How to prevent hidden field validation. In my form i have a select box, if i select one option some fields are visible, if select another option then other fields are visible and the previous fields are hidden.

    • Andreza Pollyana

      Hi, maybe this kind of validator will help you

      ‘note’: [“”, Validators.nullValidator]

  • manoj meshram

    HI,
    haserror is not function in ionic2 beta 11.

  • EM Products

    hi, thanks for the great post
    any upcoming update for the post
    also how can I validate for retype password ??

  • Eduardo Borges

    Greate!!

  • Lior Balmas

    Thanks for the article.
    I get this error:
    “Can’t bind to ‘ngFormModel’ since it isn’t a known native property”

    I use beta.11

  • Ansar Zhalyalov

    Unfortunately doesn’t work in beta 11 – “ORIGINAL EXCEPTION: No value accessor for ””

    • Franck Didier

      +1 doesn’t work

      • An article has been updated to Ionic v2 2.2.1 version.

  • Hi, Thanks for effort, the only problem is ionic2 and angular2 have had a lot of breaking changes, also the article doesn’t have published date (or mentioning ionic2 and angular2 version that this is based on), then it will be so confusing.

    • An article has been updated to Ionic v2 2.2.1 version. Plus article always had published date; on the second page; at the beginning of the Code chapter.

      Thought; I should move this information to the first page; it makes more sense. Thank you for your observation.

  • Periyasamy M

    Thank you so much.This is working fine..particular working in latest ionic 2 version and angular 2 rc versions. Thank you once again .@gajotres

  • Tammanoon K

    Thank you for reply i’ll try this.

  • Stevenson Nelli

    Could you please provide example with ionic select field ??