Membuat Login dan Register Ionic 4 - Mari Belajar Coding

Jumat, 14 Februari 2020

Membuat Login dan Register Ionic 4

Membuat Login Register Ionic 4

Dalam tutorial kali ini kita akan belajar membuat sebuah aplikasi mobile dengan framework ionic 4 untuk login dan register user. Aplikasi yang akan kita buat menggunakan ionic 4 tipe angular. 

Penggunaan web service untuk pertukaran data antar server dengan aplikasi client yang akan kita gunakan menggunakan slim framework yang pernah saya buatkan tutorial sebelumnya. Silahkan teman-teman pelajari dulu sebelum memulai membuat aplikasi login dan register ionic 4 ini. Membuat RESTFul Api Slim Framework dengan Authorization JWT .

Membuat Login dan Register Ionic 4

Buat aplikasi ionic 4 baru melalui cmd atau terminal dengan mengetikkan perintah berikut ini.

ionic start MyAppIonic4 blank --type=angular --cordova

Membuat Login dan Register Ionic 4

Setelah aplikasi MyappIonic4 selesai dibuat, buka folder MyappIonic4 kemudian buat halaman baru untuk login dan register melalui terminal.

ionic g page login

ionic g page register

Membuat Login dan Register Ionic 4

Selanjutnya buat service untuk pemanggilan rest api dan guard untuk mengamankan route halaman melalui terminal. Pilih CanActivate saat create guard.

ionic g service services/service

ionic g guard guards/auth

Membuat Login dan Register Ionic 4

Buka app.module.ts kemudian tambahkan module seperti baris dibawah ini yang di beri highlight.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';

import { HttpClientModule }    from '@angular/common/http';
import { RegisterPageModule } from './register/register.module';

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    BrowserModule, 
    IonicModule.forRoot(), 
    AppRoutingModule,
    HttpClientModule,
    RegisterPageModule
  ],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}


Buka service.service.ts untuk membuat beberapa fungsi seperti cek token, login, register, logout dan autentikasi. 

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { tap, timeout } from 'rxjs/operators';
import { ReplaySubject } from 'rxjs';
import { Platform, ToastController } from '@ionic/angular';

@Injectable({
  providedIn: 'root'
})
export class ServiceService {

  DataLogin:any;
  DataCheckLogin:any;
  authenticationState = new ReplaySubject();
  token:any;

  API_URL = 'http://localhost:88/slimrestjwt/public/'; 
  
  TOKEN_KEY = 'token';

  constructor(
    private http: HttpClient, 
    private platform: Platform,
    public toastController: ToastController
  ) {
    this.platform.ready().then(() => {
      this.checkToken();
    });
   }

  //ika token tidak ada maka authenticationState=false
  //jika token ada maka akan memanggil fungsi cekUser 
  checkToken() {
    if(localStorage.getItem(this.TOKEN_KEY)==null || localStorage.getItem(this.TOKEN_KEY)=='') {
      this.authenticationState.next(false);     
    }else{
      this.CekUser().subscribe(data => {
        this.DataCheckLogin=data;
        if(this.DataCheckLogin.status=="success"){
          this.authenticationState.next(true);          
        }else{
          this.authenticationState.next(false);
        }
     },
     err => {
        this.authenticationState.next(false);
      });
    }                                                                                                      
  }

  //cek user di sisi server dengan headers authorize bearer
  //teman-teman dapat membuat fungsi baru untuk request data lainnya dengan header authorize bearer
  CekUser(){
    //ambil data dari localstorage
    let dataStorage=JSON.parse(localStorage.getItem(this.TOKEN_KEY));
     this.token=dataStorage.token;    
      const headers = new HttpHeaders({
        'Content-Type': 'application/json',
        'Authorization': "Bearer "+this.token
      });   
    return this.http.get(this.API_URL + 'api/user/'+dataStorage.data.IdUser, { headers: headers }).pipe(
      timeout(8000),
      tap(Data => {
        return Data;
      })
    );
  }

  //login
  loginApi(credentials, type){  
    const headers = new HttpHeaders({
      'Content-Type': 'application/json',
    });
    return this.http.post(this.API_URL + type, credentials, { headers: headers }).pipe(
      tap(Data => {
        this.DataLogin=Data;
        if(this.DataLogin.status=="success"){
          localStorage.setItem(this.TOKEN_KEY, JSON.stringify(Data));
          this.authenticationState.next(true);
        }else{
          this.authenticationState.next(false);
        }
        return Data;
      })
    );
  }

  //register
  RegisterApi(credentials, type){    
    const headers = new HttpHeaders({
      'Content-Type': 'application/json',
    });
    return this.http.post(this.API_URL + type, credentials, { headers: headers }).pipe(
      tap(Data => {
        this.DataLogin=Data;
        if(this.DataLogin.status=="success"){
          localStorage.setItem(this.TOKEN_KEY, JSON.stringify(Data));
          this.authenticationState.next(true);
        }else{
          this.authenticationState.next(false);
        }
        return Data;
      })
    );
  }

  //logout
  logout() {
    this.authenticationState.next(false);
  }
}

Buka auth.guard.ts, auth guard ini berfungsi untuk autentikasi route halaman.

import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';

import { ServiceService } from '../services/service.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  
  authstatus:any;

  constructor(
    private serviceService: ServiceService
  ) {}

  canActivate(): boolean {
    this.serviceService.authenticationState.subscribe((data) => {
      this.authstatus=data;
    });
    return this.authstatus;
  }
  
}

Selanjutnya buka app.component.ts, kita akan menambahkan fungsi auth. fungsi ini akan memanggil fungsi yang berada di service dan mengecek status autentikasi true atau false. jika true maka akan di redirect ke halaman home jika false akan di redirect ke halaman login.

import { Component } from '@angular/core';

import { Platform, NavController } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { ServiceService } from './services/service.service';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})
export class AppComponent {
  constructor(
    private platform: Platform,
    private splashScreen: SplashScreen,
    private statusBar: StatusBar,
    private serviceService: ServiceService,
    private navCtrl: NavController,
  ) {
    this.initializeApp();
  }

  initializeApp() {
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
      this.Auth();
    });
  }

  Auth(){
    this.serviceService.authenticationState.subscribe((data) => {
      if (data==true) {
          this.navCtrl.navigateRoot(['home']);
        } else {
          this.navCtrl.navigateRoot(['login']);
        }
   });
  }
}

Untuk mengamankan setiap rute halaman, kita tambahkan guard yang tadi telah dibuat di app-routing.module.ts, perhatikan baris yang diberi highlight. teman-teman dapat menambahkan halaman baru dengan canActive untuk autentikasi.

import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';

import { AuthGuard } from './guards/auth.guard';

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'home', 
    canActivate: [AuthGuard],
    loadChildren: () => import('./home/home.module').then( m => m.HomePageModule)},
  {
    path: 'login',
    loadChildren: () => import('./login/login.module').then( m => m.LoginPageModule)
  },
  {
    path: 'register',
    loadChildren: () => import('./register/register.module').then( m => m.RegisterPageModule)
  },
];

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

Buka login.module.ts, tambahkan reactive form module seperti dibawah ini.

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

import { IonicModule } from '@ionic/angular';

import { LoginPageRoutingModule } from './login-routing.module';

import { LoginPage } from './login.page';

import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    LoginPageRoutingModule,
    ReactiveFormsModule,
  ],
  declarations: [LoginPage]
})
export class LoginPageModule {}

Selanjutnya buka login.page.ts, kita akan menambahkan formgrup login, fungsi request login, dan menu modal popup untuk halaman register.

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroupDirective, FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms';
import { NavController, ModalController, LoadingController, ToastController,Platform } from '@ionic/angular';
import { RegisterPage } from '../register/register.page';
import { ServiceService } from '../services/service.service';

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

  FormLogin:FormGroup;
  showPasswordText:any;
  dataLogin:any;

  constructor(
    private formBuilder: FormBuilder, 
    private navCtrl: NavController, 
    public loadingController: LoadingController,
    public modalController: ModalController,
    private platform: Platform,
    public toastController: ToastController,
    private serviceService: ServiceService,
  ) { }

  ngOnInit() {
    //setting form login
    this.FormLogin=this.formBuilder.group({
      Username:['',Validators.required],
      Password:['',Validators.required]
    });
  }

  //fungsi login
  async login(){
    //menampilkan loading
    const loading = await this.loadingController.create({
      message: 'Please wait...'
    });
    await loading.present(); 
    //memanggil fungsi loginapi yang berada di service
    this.serviceService.loginApi(this.FormLogin.value,'login').subscribe(
      data => {
        this.dataLogin=data;
        if(this.dataLogin.status=="error"){
          let message='Nama pengguna dan kata sandi yang Anda masukkan tidak cocok. Silahkan periksa dan coba lagi.';
          this.presentToast(message);
        }
        loading.dismiss();
      },
      error => {
        let message='Tidak ada koneksi internet. Silakan periksa koneksi Anda.';
        this.presentToast(message);
        loading.dismiss();
      }
    );
  }

  //menampilkan halaman register
  async registerModal() {
    const modal = await this.modalController.create({
      component: RegisterPage
    });
    return await modal.present();
  }

  async presentToast(Message) {
    const toast = await this.toastController.create({
      message: Message,
      duration: 2500,
      position: "bottom"
    });
    toast.present();
  }

}

Edit file login.page.html untuk membuat tampilan form login dan button register.

<ion-content class="ion-padding">
  <ion-grid>
    <ion-row>
      <ion-col><br />
        <img  src="https://1.bp.blogspot.com/-Mi344UDQbL0/XNhdoaxMTUI/AAAAAAAALQs/wI4GXX79ZdwJ2kA4w1PXQ_J4nXi3Yp4dQCPcBGAYYCw/s320/logo%2B2.png" width="30%" /><br /><br />
      </ion-col>
    </ion-row>
  </ion-grid>
  <form [formGroup]="FormLogin" (ngSubmit)="login()">
    <ion-item>
      <div color="dark"  slot="start">
        <ion-icon slot="icon-only" name="person" ></ion-icon>
    </div>
      <ion-input type="text" name="Username" placeholder="Username" formControlName="Username"></ion-input>
    </ion-item>  
    <ion-item>
      <div color="dark"  slot="start">
        <ion-icon slot="icon-only" name="lock-closed"></ion-icon>
    </div>
      <ion-input type="text" name="password" placeholder="Password" formControlName="Password" *ngIf="showPasswordText"></ion-input>
      <ion-input type="password" name="password" placeholder="Password"  formControlName="Password" *ngIf="!showPasswordText"></ion-input>
      <ion-icon color="dark" slot="icon-only" (click)="showPasswordText = !showPasswordText" *ngIf="showPasswordText" name="eye"  slot="end" class="ion-align-self-center"></ion-icon>
      <ion-icon color="dark" slot="icon-only" (click)="showPasswordText = !showPasswordText" *ngIf="!showPasswordText" name="eye-off" slot="end" class="ion-align-self-center"></ion-icon>
    </ion-item>
    <p class="ion-text-right">Forgot Password?</p>
    <ion-button type="submit" expand="block" color="primary" [disabled]="!FormLogin.valid">Login</ion-button>
  </form>
  <p class="ion-text-center">Don't have a account?</p>
  <ion-button expand="block" color="danger" (click)="registerModal()" >Register</ion-button>  
</ion-content>

Tambahkan css untuk mempercantik tampilan form login di login.page.css.

ion-list{
    background-color: transparent;
    padding: 0;
}
ion-row {
    align-items: center;
    text-align: center;
    }
ion-item {
    border-radius: 10px !important;
    font-size: 0.9em;
    margin-bottom: 15px;
    border: 1px solid rgba(34, 34, 34, 0.096);
    border-bottom: 0px !important;
    
    background-color: #ffffff;
    -webkit-box-shadow: 4px 8px 6px -6px #222;
    -moz-box-shadow: 4px 8px 6px -6px #222;
    box-shadow: 4px 4px 6px -6px #222;
}

Tampilan form login seperti gambar dibawah ini.
Membuat Login dan Register Ionic 4
Buka file home.page.ts, kita akan membuat fungsi logout dan fungsi untuk menampilkan username.

import { Component, OnInit } from '@angular/core';
import { LoadingController } from '@ionic/angular';
import { ServiceService } from '../services/service.service';
@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {
  Username:any;
  constructor(
    public loadingController: LoadingController,
    private serviceService: ServiceService
  ) {}

  ngOnInit() {
    //ambil data dari localstorage
    let dataStorage=JSON.parse(localStorage.getItem(this.serviceService.TOKEN_KEY));
    this.Username=dataStorage.data.Username;
  }

  async logout(){
    const loading = await this.loadingController.create({
      message: 'Please wait...'
    });
    await loading.present(); 
    localStorage.clear();
    this.serviceService.logout();
    loading.dismiss();
   }
}

Buka file home.page.html untuk mengubah tampilan home dengan menambahkan button logout.

<ion-header translucent>
  <ion-toolbar color="primary">
    <ion-title>
      Maribelajarcoding
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content fullscreen>
  <div id="container">
    <strong>Selamat datang, {{Username}}</strong>
    <p>Start with Ionic <a target="_blank" rel="noopener noreferrer" href="https://ionicframework.com/docs/components">UI Components</a></p>
    <ion-button color="danger" (click)="logout()" >Logout</ion-button>
  </div>
</ion-content>

Tampilan halaman home seperti gambar dibawah ini.

Membuat Login dan Register Ionic 4
Selanjutnya kita akan membuat halaman register user. Sama halnya dengan halaman login, aktifkan juga reactive form module yang berada di file register.module.ts.

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

import { IonicModule } from '@ionic/angular';

import { RegisterPageRoutingModule } from './register-routing.module';

import { RegisterPage } from './register.page';

import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    RegisterPageRoutingModule,
    ReactiveFormsModule
  ],
  declarations: [RegisterPage]
})
export class RegisterPageModule {}

Selanjutnya kita buka register.page.ts untuk setting form group, validasi form, dan fungsi register seperti dibawah ini.

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroupDirective, FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms';
import { NavController, LoadingController, ToastController, Platform, ModalController, AlertController } from '@ionic/angular';
import { ServiceService } from '../services/service.service';

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

  showPasswordText:any;
  showKonfirmPasswordText:any;

  validations = {
    'Username': [
      { type: 'required', message: 'Username harus diisi.' },
      { type: 'validUsername', message: 'Username sudah terdaftar.' }
    ],
    'Password': [
      { type: 'required', message: 'Password harus diisi.' },
      { type: 'minlength', message: 'Password minimal harus 5 karakter.' },
      { type: 'pattern', message: 'Password harus mengandung huruf (baik huruf besar dan kecil) dan angka.' },
    ],  
    'NamaLengkap': [
      { type: 'required', message: 'Nama lengkap harus diisi.' },      
    ],   
    'Email': [
      { type: 'required', message: 'Email harus diisi.' },
      { type: 'pattern', message: 'Email tidak valid.' },
    ],
    'NoHp': [
      { type: 'required', message: 'No Hp harus diisi.' },
      { type: 'minlength', message: 'No Hp minimal harus 10 karakter.' },
      { type: 'maxlength', message: 'No Hp maksimal harus 15 karakter.' },
    ],
  };

  FormRegister: FormGroup;
  ResponseRegister:any;

  constructor(
    private formBuilder: FormBuilder, 
    private navCtrl: NavController, 
    public loadingController: LoadingController,
    private platform: Platform,
    public toastController: ToastController,
    public alertController: AlertController,
    public modalController: ModalController,
    private serviceService: ServiceService
  ) { }

  ngOnInit() {
    this.FormRegister = this.formBuilder.group({
      Username:new FormControl('', Validators.compose([
        Validators.required,
      ])),
      Password:new FormControl('', Validators.compose([
        Validators.required, 
        Validators.minLength(5),
        // Validators.pattern('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]+$')
      ])),
      NamaLengkap:new FormControl('', Validators.compose([Validators.required])),
      Email:new FormControl('', Validators.compose([
        Validators.required,
        Validators.pattern('^[\\w]+(?:\\.[\\w])*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$')
      ])),
      NoHp:new FormControl('', Validators.compose([
        Validators.required,
        Validators.minLength(10), 
        Validators.maxLength(15) 
      ]))
    });
  }

  async Register(){
    //menampilkan loading
    const loading = await this.loadingController.create({
      message: 'Please wait...'
    });
    await loading.present(); 
    //panggil fungsi register di service
    this.serviceService.RegisterApi(this.FormRegister.value,'register').subscribe(
      data => {
        this.ResponseRegister=data;
        //cek apakah register berhasil atau tidak
        if(this.ResponseRegister.status=="error"){       
          this.AlertRegister("Pendaftaran user tidak berhasil, silahkan coba lagi.");       
          loading.dismiss();
        }else{
           loading.dismiss();
          this.modalController.dismiss();
        }
        loading.dismiss();
      },
      error => {
        loading.dismiss();
      }
    );
  }

  dismissRegister() {
    this.modalController.dismiss();
  }

  async AlertRegister(Message) {
    const alert = await this.alertController.create({
      header: 'Peringatan!',
      //subHeader: 'Subtitle',
      message: Message,
      buttons: ['OK']
    });
    await alert.present();
  }

}

Buat tampilan form register di register.page.html,

<ion-header>
  <ion-toolbar color="primary">
    <ion-title class="ion-text-left">Register</ion-title>
    <ion-buttons slot="end">
      <ion-button (click)="dismissRegister()">Close</ion-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

<ion-content class="ion-padding">
  <form [formGroup]="FormRegister">
    <ion-item>
      <ion-label color="primary" position="floating">Username</ion-label>
      <ion-input type="text" name="Username" formControlName="Username"></ion-input>
    </ion-item>
    <div class="error-container">
      <ng-container *ngFor="let validation of validations.Username">
        <div class="error-message" *ngIf="FormRegister.get('Username').hasError(validation.type) && (FormRegister.get('Username').dirty || FormRegister.get('Username').touched)">
          <span>{{ validation.message }}</span>
          <br><br>
        </div>
      </ng-container>
    </div>

    <ion-item>
      <ion-label color="primary" position="floating">Password</ion-label>
      <ion-input  type="text" name="Password" formControlName="Password" *ngIf="showPasswordText" ></ion-input>
      <ion-input type="password" name="Password" formControlName="Password" *ngIf="!showPasswordText" ></ion-input>      
      <ion-icon color="dark" slot="icon-only" (click)="showPasswordText = !showPasswordText" *ngIf="showPasswordText" name="eye"  slot="end" class="ion-align-self-center"></ion-icon>
      <ion-icon color="dark" slot="icon-only" (click)="showPasswordText = !showPasswordText" *ngIf="!showPasswordText" name="eye-off" slot="end" class="ion-align-self-center"></ion-icon>
    </ion-item>
    <div class="error-container">
      <ng-container *ngFor="let validation of validations.Password">
        <div class="error-message" *ngIf="FormRegister.get('Password').hasError(validation.type) && (FormRegister.get('Password').dirty || FormRegister.get('Password').touched)">
          <span>{{ validation.message }}</span>
          <br><br>
        </div>
      </ng-container>
    </div>
    
    <ion-item>
      <ion-label color="primary" position="floating">Nama Lengkap</ion-label>
      <ion-input type="text" name="NamaLengkap" formControlName="NamaLengkap"></ion-input>
    </ion-item>
    <div class="error-container">
      <ng-container *ngFor="let validation of validations.NamaLengkap">
        <div class="error-message" *ngIf="FormRegister.get('NamaLengkap').hasError(validation.type) && (FormRegister.get('NamaLengkap').dirty || FormRegister.get('NamaLengkap').touched)">
          <span>{{ validation.message }}</span>
          <br><br>
        </div>
      </ng-container>
    </div>
  
    <ion-item>
      <ion-label color="primary" position="floating">Email</ion-label>
      <ion-input type="email" name="Email" formControlName="Email"></ion-input>
    </ion-item>
    <div class="error-container">
      <ng-container *ngFor="let validation of validations.Email">
        <div class="error-message" *ngIf="FormRegister.get('Email').hasError(validation.type) && (FormRegister.get('Email').dirty || FormRegister.get('Email').touched)">
          <span>{{ validation.message }}</span>
          <br><br>
        </div>
      </ng-container>
    </div>

    <ion-item>
      <ion-label color="primary" position="floating">No. Hp</ion-label>
      <ion-input type="text" name="NoHp" formControlName="NoHp"></ion-input>
    </ion-item>
    <div class="error-container">
      <ng-container *ngFor="let validation of validations.NoHp">
        <div class="error-message" *ngIf="FormRegister.get('NoHp').hasError(validation.type) && (FormRegister.get('NoHp').dirty || FormRegister.get('NoHp').touched)">
          <span>{{ validation.message }}</span>
          <br><br>
        </div>
      </ng-container>
    </div><br>
    
      <ion-button expand="full" color="danger" (click)="Register()" [disabled]="!FormRegister.valid">Register</ion-button>
  </form>
</ion-content>

Tambahkan css di register.page.scss.

ion-item {
    border-radius: 10px !important;
    //padding-left: 30px !important;
    font-size: 0.9em;
     margin-bottom: 4px;
    border: 1px solid rgba(34, 34, 34, 0.096);
    border-bottom: 0px !important;
    //box-shadow: none !important;
    
    background-color: #ffffff;
    -webkit-box-shadow: 4px 8px 6px -6px #222;
    -moz-box-shadow: 4px 8px 6px -6px #222;
    box-shadow: 4px 4px 6px -6px #222;
}
.error-container{
    color: red;
    font-size: 0.8em;
}

Tampilan halaman register.
Membuat Login dan Register Ionic 4

Uji coba aplikasi.

Related Posts

Load comments