Ionic4 (beta) Login, Register and Profile pages. Starter.

Oct. 2018 (en) Ionic4 Ionic 4-beta Ionic Pages

Albert Serra

We suppose that you have a ionic4 started $ ionic start MyProject blank.

1. Auth Service

We build a auth service that will we communicate with de login, register and update actions. $ ionic g service authService.

// src/app/authservice.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export class User {
  name: string;
  email: string;

  constructor(name: string, email: string) {
    this.name = name;
    this.email = email;
  }
}

@Injectable({
  providedIn: 'root'
})

export class AuthService {

  currentUser: User;
  isLogged: Boolean = false;

  constructor() { 

  }

  public login(credentials) {
    if (credentials.email === null || credentials.password === null) {
      return Observable.throw("Please insert credentials");
    } else {
      return Observable.create(observer => {
        // TODO: 
        // At this point make a request to your backend to make a real check!
        // 
        let access = (credentials.password === "pass" && credentials.email === "email");
        this.currentUser = new User('Albert', 'user@albertserra.cat');
        this.isLogged = true;
        observer.next(access);
        observer.complete();
      });
    }
  }

  public logout() {
    console.log('logout');
    return Observable.create(observer => {
      this.currentUser = null;
      observer.next(true);
      observer.complete();
    });
  }

  public register(credentials) {
    if (credentials.email === null || credentials.password === null) {
      return Observable.throw("Please insert credentials");
    } else {
      // TODO: 
      // At this point store the credentials to your backend!
      // 
      return Observable.create(observer => {
        observer.next(true);
        observer.complete();
      });
    }
  }

  public update( info ) {
    if( info.email === null || info.name === null ) {
      return Observable.throw("Please fill all fields");
    } else {
      return Observable.create(observer => {
        observer.next(true);
        observer.complete();
      });
    }
  }

  public getUserInfo() : User {
    return this.currentUser;
  }

  public logout() {
    return Observable.create(observer => {
      this.currentUser = null;
      observer.next(true);
      observer.complete();
    });
  }

  public checkLogged() {
    return this.isLogged; 
  }

}

2. Creating pages

3. Routing

// src/app/app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
  {
    path: '',
    redirectTo: 'login',
    pathMatch: 'full'
  },
  { path: 'home', loadChildren: './home/home.module#HomePageModule' },
  { path: 'register', loadChildren: './register/register.module#RegisterPageModule' },
  { path: 'logout', loadChildren: './login/login.module#LoginPageModule' },
  { path: 'login', loadChildren: './login/login.module#LoginPageModule' },
  { path: 'profile', loadChildren: './profile/profile.module#ProfilePageModule' }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

4. Login page

// src/app/login/login.page.ts

import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { AlertController, LoadingController } from '@ionic/angular';
import { AuthService } from '../auth.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.page.html',
  styleUrls: ['./login.page.scss'],
})

export class LoginPage implements OnInit {
  loading;
  registerCredentials = { email: '', password: '' };

  constructor( private router: Router, private auth: AuthService, private alertCtrl: AlertController, 
               private loadingCtrl: LoadingController ) {  } 
  ngOnInit() {
    console.log(this.router.url);
    if( this.router.url === '/logout') {
      this.logout();
    }
  }

  async login() {
    await this.showLoading();

    this.auth.login(this.registerCredentials).subscribe(allowed => {
      if (allowed) {
        this.loading.dismiss();
        this.router.navigateByUrl('/profile');
      } else {
        this.showAlert("Fail","Access Denied");
      }
    },
      error => {
        this.showAlert("Fail",error);
      });
  }

  async showLoading() {
    this.loading = await this.loadingCtrl.create({
      message: 'Loading...'
    });
    return await this.loading.present();
  }

  async showAlert(header, text) {
    console.log('show error');
    if( typeof this.loading != "undefined" ) this.loading.dismiss();

    let alert = await this.alertCtrl.create({
      header: header,
      message: text,
      buttons: ['OK']
    });

    alert.present();
  }

  public logout() {
    console.log('logout');
    this.auth.logout();
    this.showAlert("Logout", "You have successfully logged out");
  }

}
// src/app/login/login.page.html
<ion-header>
  <ion-toolbar>
    <ion-title>login</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>

<div class="login-box">
    <form (ngSubmit)="login()" #registerForm="ngForm">
      <ion-row>
        <ion-col>
          <ion-list inset>

            <ion-item>
              <ion-input type="text" placeholder="Email" name="email" [(ngModel)]="registerCredentials.email" required></ion-input>
            </ion-item>

            <ion-item>
              <ion-input type="password" placeholder="Password" name="password" [(ngModel)]="registerCredentials.password" required></ion-input>
            </ion-item>

          </ion-list>
        </ion-col>
      </ion-row>

      <ion-row>
        <ion-col class="signup-col">
          <ion-button class="submit-btn" full type="submit" [disabled]="!registerForm.form.valid">Login</ion-button>
        </ion-col>
      </ion-row>

      <ion-row>
        <a class="register-btn" block clear href="/register">Create New Account</a>
      </ion-row>

    </form>
  </div>

</ion-content>

5. Register Page

// src/app/register/register.page.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { NavController,AlertController, LoadingController } from '@ionic/angular';
import { AuthService } from '../auth.service';

@Component({
  selector: 'app-register',
  templateUrl: './register.page.html',
  styleUrls: ['./register.page.scss'],
})
export class RegisterPage {

  createSuccess = false;
  registerCredentials = { email: '', password: '' };

  constructor( private router: Router, private nav: NavController, 
               private auth: AuthService, private alertCtrl: AlertController, 
               private loading: LoadingController ) { }

  public register() {
    this.auth.register(this.registerCredentials).subscribe(success => {
      if (success) {
        this.createSuccess = true;
        this.showPopup("Success", "Account created.");
      } else {
        this.showPopup("Error", "Problem creating account.");
      }
    },
    error => {
      this.showPopup("Error", error);
    });
  }

  async showPopup(title, text) {
    let alert = await this.alertCtrl.create({
      header: title,
      message: text,
      buttons: [
        {
          text: 'OK',
          handler: data => {
            if (this.createSuccess) {
              // console.log('create successs');
              this.router.navigateByUrl('/home');
            }
          }
        }
      ]
    });

    return await alert.present();
  }

}
// src/app/register/register.page.html
<ion-header>
  <ion-toolbar>
    <ion-title>register</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>
<div class="login-box">

    <form (ngSubmit)="register()" #registerForm="ngForm">
      <ion-row>
        <ion-col>
          <ion-list inset>

            <ion-item>
              <ion-input type="text" placeholder="Email" name="email" [(ngModel)]="registerCredentials.email" required></ion-input>
            </ion-item>

            <ion-item>
              <ion-input type="password" placeholder="Password" name="password" [(ngModel)]="registerCredentials.password" required></ion-input>
            </ion-item>

          </ion-list>
        </ion-col>
      </ion-row>

      <ion-row>
        <ion-col class="signup-col">
          <ion-button class="submit-btn" full type="submit" [disabled]="!registerForm.form.valid">Register</ion-button>
        </ion-col>
      </ion-row>

    </form>
  </div>
</ion-content>

6. Profile page

// src/app/profile/profile.page.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { AlertController, LoadingController } from '@ionic/angular';
import { User, AuthService } from '../auth.service';

@Component({
  selector: 'app-profile',
  templateUrl: './profile.page.html',
  styleUrls: ['./profile.page.scss'],
})
export class ProfilePage {

  saveSuccess = false;
  info: User;

  constructor( private router: Router,
    private auth: AuthService, private alertCtrl: AlertController, 
    private loading: LoadingController ) { 

      if( this.auth.checkLogged() ) {
        this.info = this.auth.getUserInfo(); 
      } else {
        console.log('not logged');
        this.router.navigateByUrl('/login');
      }
  }

  public save() {
    this.auth.register(this.info).subscribe(success => {
      if (success) {
        this.saveSuccess = true;
        this.showPopup("Success", "Thanks! Profile updated.");
      } else {
        this.showPopup("Error", "Problem updating profile.");
      }
    },
    error => {
      this.showPopup("Error", error);
    });
  }

  async showPopup(title, text) {
    let alert = await this.alertCtrl.create({
      header: title,
      message: text,
      buttons: [
        {
          text: 'OK',
          handler: data => {
            if (this.saveSuccess) {
              // console.log('create successs');
              this.router.navigateByUrl('/home');
            }
          }
        }
      ]
    });

    return await alert.present();
  }

}
// src/app/profile/profile.page.html
<ion-header>
  <ion-toolbar>
    <ion-title>profile</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>

  <div class="login-box">

    <form (ngSubmit)="save()" #saveForm="ngForm">
      <ion-row>
        <ion-col>
          <ion-list inset>

            <ion-item>
              <ion-input type="text" placeholder="Name" name="name" [(ngModel)]="info.name" required></ion-input>
            </ion-item>

            <ion-item>
              <ion-input type="text" placeholder="Email" name="email" [(ngModel)]="info.email" required></ion-input>
            </ion-item>

            <ion-item>
              <ion-input type="password" placeholder="Password" name="password" [(ngModel)]="info.password" ></ion-input>
              <small>Blank field don't modify password</small>
            </ion-item>

          </ion-list>
        </ion-col>
      </ion-row>

      <ion-row>
        <ion-col class="signup-col">
          <ion-button class="submit-btn" full type="submit" [disabled]="!saveForm.form.valid">Save</ion-button>
        </ion-col>
      </ion-row>

    </form>
  </div>

</ion-content>

7. Next. Local Storage.

$ ionic serve

Thanks

EOF