The form is initialized like this in auth.js:
 
this.authForm = formBuilder.group({
	username: ['', Validators.compose([Validators.required, Validators.pattern('[a-zA-Z]*'), Validators.minLength(8), Validators.maxLength(30)])],
	password: ['', Validators.compose([Validators.required, Validators.minLength(8)])]
});
 
We’re using FormBuilder helper service formBuilder to group form fields into ControlGroup object called authForm.
 
I hope all this make sense. It’s almost funny, but validation is the easiest part here. 🙂
 
Everything shown here makes an Angular 2 form, but what about validation?
 
Let’s once again take a look at these lines:
 
username: ['', Validators.compose([Validators.required, Validators.pattern('[a-zA-Z]*'), Validators.minLength(8), Validators.maxLength(30)])],
password: ['', Validators.compose([Validators.required, Validators.minLength(8)])]
 
We have defined four validation rules for the username field and two validation rules for the password filed. All these rules except pattern are predefined and you can use them any way you want. While the pattern is also preexisting validation rule you still need to provide a working regex pattern.
 
<ion-item [ngClass]="{'error-border':!authForm.controls.password.valid && authForm.controls.password.touched}">
	<ion-label floating>Password</ion-label>
	<ion-input formControlName="password" type="password"></ion-input>
</ion-item>
<ion-item *ngIf="authForm.controls.password.hasError('required') && authForm.controls.password.touched">
	<p>Sorry, field password is required!</p>
</ion-item>
<ion-item *ngIf="authForm.controls.password.hasError('minlength') && authForm.controls.password.touched">
	<p>Sorry, minimum password length is 8!</p>
</ion-item>
 
If the password field is not valid (!authForm.controls.password.valid) after a field has been touched (authForm.controls.password.touched) Angular will add a class error-border to ion-item element:
 
<ion-item [ngClass]="{'error-border':!authForm.controls.password.valid && authForm.controls.password.touched}">
 
authForm.controls.password keyword is a reference to password Control object.
 
At the same time, below each field, we can find a few additional div elements holding error descriptions. In the case of fields (username or password) have validation errors, a related description will become visible.
 
<ion-item *ngIf="authForm.controls.password.hasError('required') && authForm.controls.password.touched">
	<p>Sorry, field password is required!</p>
</ion-item>
<ion-item *ngIf="authForm.controls.password.hasError('minlength') && authForm.controls.password.touched">
	<p>Sorry, minimum password length is 8!</p>
</ion-item>
 
Finally, if everything is OK and application form is successfully validated, we’ll enable submit button:
 
<button ion-button full color="primary" [disabled]="!authForm.valid" style="margin-top: 20px;" type="submit">Authorize</button>
 

Code

 
In the case, GitHub repository below is not available and you can only use the code provided below, this is what project folder looks like (image was taken from the Sublime text editor):
 
Ionic 2 Form Validation Folder Structure
 
app.component.ts
import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

import { HomePage } from '../pages/home/home';
import { AuthPage } from '../pages/auth/auth';

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

export class MyApp {
  rootPage:any;

  constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) {
    platform.ready().then(() => {
      statusBar.styleDefault();
      splashScreen.hide();
      this.checkPreviousAuthorization();
    });
  }

  checkPreviousAuthorization(): void { 
    if((window.localStorage.getItem('username') === "undefined" || window.localStorage.getItem('username') === null) && 
       (window.localStorage.getItem('password') === "undefined" || window.localStorage.getItem('password') === null)) {
      this.rootPage = AuthPage;
    } else {
      this.rootPage = HomePage;
    }
  }  
}
 
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
 
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { AuthPage } from '../pages/auth/auth';
 
@NgModule({
  declarations: [
    MyApp,
    HomePage,
    AuthPage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage,
    AuthPage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}
 
auth.html
<ion-header>
  <ion-navbar>
    <ion-title>Authorization Page</ion-title>
  </ion-navbar>
</ion-header>
 
 
<ion-content padding>
    <form [formGroup]="authForm" (ngSubmit)="onSubmit(authForm.value)">
        <ion-item [ngClass]="{'error-border':!authForm.controls.username.valid && authForm.controls.username.touched}">
            <ion-label floating>Username</ion-label>
            <ion-input formControlName="username" type="text"></ion-input>
        </ion-item>
 
        <ion-item *ngIf="authForm.controls.username.hasError('required') && authForm.controls.username.touched">
            <p>Sorry, field username is required!</p>
        </ion-item>
        <ion-item *ngIf="authForm.controls.username.hasError('pattern') && authForm.controls.username.touched">
            <p>Sorry, only small and capital letters are allowed!</p>
        </ion-item>        
        <ion-item *ngIf="authForm.controls.username.hasError('minlength') && authForm.controls.username.touched">
            <p>Sorry, minimum username length is 8!</p>
        </ion-item>
        <ion-item *ngIf="authForm.controls.username.hasError('maxlength') && authForm.controls.username.touched">
            <p>Sorry, maximum username length is 30!</p>
        </ion-item>
 
        <ion-item [ngClass]="{'error-border':!authForm.controls.password.valid && authForm.controls.password.touched}">
            <ion-label floating>Password</ion-label>
            <ion-input formControlName="password" type="password"></ion-input>
        </ion-item>
        <ion-item *ngIf="authForm.controls.password.hasError('required') && authForm.controls.password.touched">
            <p>Sorry, field password is required!</p>
        </ion-item>
        <ion-item *ngIf="authForm.controls.password.hasError('minlength') && authForm.controls.password.touched">
            <p>Sorry, minimum password length is 8!</p>
        </ion-item>                
 
        <button ion-button full color="primary" [disabled]="!authForm.valid" style="margin-top: 20px;" type="submit">Authorize</button>        
    </form>
</ion-content>
 
auth.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators, AbstractControl } from '@angular/forms';
import { IonicPage, NavController, NavParams } from 'ionic-angular';

import { HomePage } from '../home/home';

@IonicPage()
@Component({
  selector: 'page-auth',
  templateUrl: 'auth.html',
})

export class AuthPage {

	authForm: FormGroup;

	constructor(public nav: NavController, public navParams: NavParams, public formBuilder: FormBuilder) {

		this.nav = nav;

	    this.authForm = formBuilder.group({
	        username: ['', Validators.compose([Validators.required, Validators.pattern('[a-zA-Z]*'), Validators.minLength(8), Validators.maxLength(30)])],
	        password: ['', Validators.compose([Validators.required, Validators.minLength(8)])]
	    });
	}

	onSubmit(value: any): void { 
	    if(this.authForm.valid) {
			window.localStorage.setItem('username', value.username);
			window.localStorage.setItem('password', value.password);

			this.nav.push(HomePage);
	    }
	}   
}
 
home.html
https://www.gajotres.net/wp-admin/post.php?post=10371&action=edit#
<ion-header>
  <ion-navbar hideBackButton>
    <ion-title>Home Page</ion-title>
  </ion-navbar>
</ion-header>
 
<ion-content padding>
  <h1>Welcome {{username}}</h1>
  <button ion-button full color="primary" style="margin-top: 20px;" (click)="logout()">Logout</button>
</ion-content>
 
home.ts
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
 
import { AuthPage } from '../auth/auth';
 
@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
 
    username: string;
 
    constructor(public nav: NavController) {
        this.nav = nav;
        this.username = window.localStorage.getItem('username');
    }

	logout() {
        window.localStorage.removeItem('username');
        window.localStorage.removeItem('password');

        this.nav.setRoot(AuthPage);
        this.nav.popToRoot();         
	}    
}
 

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, as this example is not bound to any platform, you can run it in your browser:
 
ionic serve -l -c -s
 

Download The Code

 
Working GitHub repo link can be found below:
 
GitHub
 
 

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.