# 12th April Report This is the seventh study report of NTUST Internship program, before going to Taiwan. More stuff will be added soon because I had a lot of homeworks. In here I will explain briefly how to create login and register page using Ionic 4 as PWA. We will using previous reports, which is service worker and manifest, to build PWA. ## Summary of this week - Make login and register page using Ionic 4 - Login page will consists of email and password input - Login will call authentication service from Firebase, and if the user not found then it will notify error in console - Register page will consists of email and password with re-password which used as confirmation - When the user is register, the email and password will stored in authentication service of Firebase, and be used for login - Using Firebase authentication service for login and register - Import the Firebase authentication library for using authentication service to project - Get API key and configuration from Firebase so web app can identify the account for storing - What we need here: | Check | Things we need | |---|---| | | Create Ionic 4 project, blank page also work. | | | Install the angular service worker into the project. | | | Initialize the pages, include login and register. | | | Use Firebase account for authentication service, we may register first if not have one. | | | Install the firebase angular for PWA. | | | Coding the web app. | | | Deploy! or run it locally works as well. | --- ## Documentation ### 1. Create Ionic 4 project From the previous reports we have known how to create Ionic 4 project for create PWA. Using the command line or terminal: `ionic start myApp blank` We know that "myApp" is the name of our project, we can change to whatever name we want. Then, go into the directory of our project: `cd myApp` Install the angular service worker there, FYI beforehand we need to install Angular through Node JS first: `ng add @angular/pwa` After that, install Angular Firebase library with Node JS command line: `npm install firebase @angular/fire --save` From this, we have done three things: | Check | Things we need | |---|---| |✔| Create Ionic 4 project, blank page also work. | |✔| Install the angular service worker into the project. | || Initialize the pages, include login and register. | || Use Firebase account for authentication service, we may register first if not have one. | |✔| Install the firebase angular for PWA. | || Coding the web app. | || Deploy! or run it locally works as well. | ### 2. Initialize the pages Inside of our project we can add more pages beside of "main" page, basically it called home page. Simply, we need to type this: `ionic generate page loginpage` - **ionic generate** is command for generating something into the Ionic project - If you type without "page loginpage" you can get any Ionic feature, like: page, component, service, etc. - **loginpage** is the name of new page, we can change to whatever we want, also we can create the page inside the folder, for example: `ionic generate page auth/loginpage` - With using folder, the pages is distributed clearly so they don't stack in the "app" or main folder After login page, we can also add register page for registering the user, reset page for user who want to reset the password or recover his account, or anything into the project. If we already have the design of web app, we can create pages with nested folder without doing it manually. After that, we can check into our project, it should have like this: <center> <img src="https://raw.githubusercontent.com/aru1702/images/master/ntust-documentation/08-01.JPG" alt="img-01"> </center> </br> From this, we have done three things: | Check | Things we need | |---|---| |✔| Create Ionic 4 project, blank page also work. | |✔| Install the angular service worker into the project. | |✔| Initialize the pages, include login and register. | || Use Firebase account for authentication service, we may register first if not have one. | |✔| Install the firebase angular for PWA. | || Coding the web app. | || Deploy! or run it locally works as well. | ### 3. Initialize project with Firebase Firebase is Google platform for mobile and web app development. It has many feature including hosting and database. In here, we will using authentication service, or feature, to store registered user and to use it for login. Simply, if you don't have Firebase account yet, using Google account and go to [Firebase Official Website](https://firebase.google.com/) because it is from Google. Just follow the instruction, create project (named it with anything you like), and go to the dashboard. Here we go: <center> <img src="https://raw.githubusercontent.com/aru1702/images/master/ntust-documentation/08-02.JPG" alt="img-02"> </center> </br> Look on the Project Overview and click the gear button to get into Project Settings. Inside, scroll down through "Your Apps" and you will found a symbol of code (like this: **</>**), click on it. You will get some code for using your Firebase API into web app project. <center> <img src="https://raw.githubusercontent.com/aru1702/images/master/ntust-documentation/08-03.JPG" alt="img-03"> </center> </br> Copy paste the code and open our code project. Inside the "src/app" folder, create new file with name **firebase.ts**. :::info As for you know, the name "firebase.ts" is just a name, you can change to whatever you want but using firebase.ts to use it further with ease. The important point is it must be in **TypeScript** type file so remember to use (.ts). ::: Modify a little so it can be use in Ionic 4 project: ```typescript= const config = { apiKey: "YOUR_API_KEY", authDomain: "YOUR_DOMAIN", databaseURL: "YOUR_DATABASE_URL", projectId: "YOUR_PROJECT_ID", storageBucket: "YOUR_STORAGE", messagingSenderId: "YOUR_SENDER_ID" }; export default config ``` *The thing with full UPPERCASE inside the code one to another is different, and private. So above there I defined it with UPPERCASE to hide from public. Just copy-paste the thing like code above. From this, we have done three things: | Check | Things we need | |---|---| |✔| Create Ionic 4 project, blank page also work. | |✔| Install the angular service worker into the project. | |✔| Initialize the pages, include login and register. | |✔| Use Firebase account for authentication service, we may register first if not have one. | |✔| Install the firebase angular for PWA. | || Coding the web app. | || Deploy! or run it locally works as well. | ### 4. Coding Time! Now let's start code our project! Don't worry it is not as complex as previous report but we need certain understanding like storing something into services. I will explain file per file we need. Also, I will a comment to identify which code we need to add into our source code so you don't need to copy-paste all over it. Just understand from where you have to adjust the source code. If you copy-paste all the code, make sure you adjust with your project, like the name or some directory, and also delete all the comment because some of the comment I gave is not properly to be commented. This means the source code it self cannot add a comment. For example: ```c= for (i=1; // this is not proper comment // but I stated here to help understand the code // so just delete the comment i<100; i++) ``` #### 4.1. app.module.ts You can find the file in "src/app" ```typescript= 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 { ServiceWorkerModule } from '@angular/service-worker'; import { environment } from '../environments/environment'; // import firebase configuration and angular library for firebase import firebaseConfig from './firebase'; import { AngularFireModule } from '@angular/fire'; import { AngularFireAuthModule } from '@angular/fire/auth'; // end of add @NgModule({ declarations: [AppComponent], entryComponents: [], imports: [ BrowserModule, IonicModule.forRoot(), AppRoutingModule, ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production // initialize firebase to project AngularFireModule.initializeApp (firebaseConfig), AngularFireAuthModule // end of add ], providers: [ StatusBar, SplashScreen, { provide: RouteReuseStrategy, useClass: IonicRouteStrategy } ], bootstrap: [AppComponent] }) export class AppModule {} ``` - We need to import the Angular library for Firebase (remember the **@angular/fire** ?) to app.module so it can be use. - We also import the TypeScript file that contains our Firebase configuration, the one that named "firebase.ts", it is not as **'./firebase.ts'** - Inside the @NgModule import, we declare Angular Firebase using the configuration file. - Also we declare the use of AuthModule to use the authentication service. #### 4.2. home.page.html Because of we just create the page, it is not like we have done the routing process. Routing is PWA feature which we can change the page by page without displaying browser like reload. Interestingly, it will displayed as like we use native app, from menu to menu. ```htmlmixed= <ion-header> <ion-toolbar> <ion-title>Home</ion-title> </ion-toolbar> </ion-header> <ion-content> <ion-list> <ion-item (click)="login()"> <ion-label>Login Page</ion-label> </ion-item> <ion-item (click)="register()"> <ion-label>Register Page</ion-label> </ion-item> <ion-item (click)="reset()"> <ion-label>Reset Password</ion-label> </ion-item> </ion-list> </ion-content> ``` - In here, we using **`<ion-list>`** to create list of somethings, just like `<li>` and `<ul>` in HTML, with using Ionic theme. - Inside list, actually we can just add anything inside, not like "list" in HTML code. I think it is like the mix of `<div>` and "list" code. - **`<ion-item>`** is use for creating item that we want to add some feature inside it. The item itself can be photo, text, or anything. - **`<ion-label>`** is use for creating label on something, in here it is not necessary if you don't want it but using this will make the text displayed with Ionic theme. - Also, using the ion thing will make us can modify using Ionic theme whatever we want. - **`(click)="login()"`** is the command for Ionic feature that anything Ionic with this command can be click and call the function inside the TypeScript. Simply, it's like a "link" of the item to the function that is called. After that, we will have like this: <center> <img src="https://raw.githubusercontent.com/aru1702/images/master/ntust-documentation/08-04.JPG" alt="img-04"> </center> </br> #### 4.3. home.page.ts ```typescript= import { Component } from '@angular/core'; // we import the Router module from Angular import { Router } from '@angular/router'; // end of add @Component({ selector: 'app-home', templateUrl: 'home.page.html', styleUrls: ['home.page.scss'], }) export class HomePage { // add parameter to constructor constructor (private router: Router) {} // end of add // add routing to login, register, and reset page login() { this.router.navigate(['login']); } register() { this.router.navigate(['register']); } reset() { this.router.navigate(['reset']); } // end of add } ``` - Import the Router module first, then add into constructor as parameter. - We have declare something in our HTML file (the "click" thing), now we declare the functions here. - Inside of each function we just declare the navigate with 'login', 'register', although we install them inside the folder, or maybe nested folder. This is because, we can check on **src/app/app-routing.module.ts**: ```typescript= // some stuff here const routes: Routes = [ { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', loadChildren: './home/home.module#HomePageModule' }, { path: 'login', loadChildren: './auth/login/login.module#LoginPageModule' }, { path: 'register', loadChildren: './auth/register/register.module#RegisterPageModule' }, { path: 'reset', loadChildren: './auth/reset/reset.module#ResetPageModule' }, { path: 'dashboard', loadChildren: './dashboard/dashboard.module#DashboardPageModule' }, ]; // and more stuff here ``` - We have declare them, or should I said the Ionic has declared for us, with the name and it automatically path to the each page. - For example: the **login** which we can use to navigate as login page is already path into **./auth/login/login.module#LoginPageModule** #### 4.4. login.page.html ```htmlmixed= <ion-header> <ion-toolbar> <ion-title>Login Page</ion-title> </ion-toolbar> </ion-header> <ion-content> <ion-list> <ion-item> <ion-label position="floating">Email</ion-label> <ion-input type="email" [(ngModel)]="email"></ion-input> </ion-item> <ion-item> <ion-label position="floating">Password</ion-label> <ion-input type="password" [(ngModel)]="password"></ion-input> </ion-item> <ion-button fill="solid" expand="block" color="dark" (click)="login()">Login</ion-button> </ion-list> </ion-content> ``` - Inside here we create simple login with user can fill with email and password, and press the login button to access. - In **`<ion-input>`** we have **`[(ngModel)]="variable-name"`** to use any value inside so it can be passed into TypeScript file so it can be processed. This is useful for input something into program. - **`<ion-button>`** is for creating button with Ionic theme, we can mix the design inside the bracket just like example above. After that, we will have like this: <center> <img src="https://raw.githubusercontent.com/aru1702/images/master/ntust-documentation/08-05.JPG" alt="img-05"> </center> </br> #### 4.5. login.page.ts ```typescript= import { Component, OnInit } from '@angular/core'; // import Angular Auth import { AngularFireAuth } from '@angular/fire/auth'; import { auth } from 'firebase/app'; // end of add @Component({ selector: 'app-login', templateUrl: './login.page.html', styleUrls: ['./login.page.scss'], }) export class LoginPage implements OnInit { // create variables // it should use same name as ngModel in html // because we want to passed the parameter email: string = ""; password: string = ""; // add parameter of Firebase Auth to constructor constructor(public afAuth: AngularFireAuth) { } ngOnInit() { } // add login() function which called by clicking the button async login() { const { email, password } = this; try { const res = await this.afAuth.auth.signInWithEmailAndPassword(email, password); console.log(res); } catch (err) { console.dir(err); if (err.code == "auth/user-not-found") { console.log("User not found!"); } } } } ``` - We import Firebase Auth again in here, this time for use as constructor and authentication feature from Angular firebase library. - For variable, use the same name as the **ngModel** we declared in HTML page, this because we want to have something that passed from that, other than something processed from here. - Declare the function of login() with **async** so we can use **await**, you can check [this](https://basarat.gitbooks.io/typescript/docs/async-await.html) to read about Async Await. - Declare the passed email and password as constant in login function, then use the **signInWithEmailAndPassword** to sign in using email and password. - With try-catch, it is more flexible than using if-then-else boolean expression, try-catch will run the code inside the try and will run catch whenever there is runtime error. #### 4.6. register.page.ts and register.page.html In register page, we can create just like the login page with more user input, like name, phone number, etc. The page concept is the same, some differences in TypeScript file will have this: ```typescript const res = await this.afAuth.auth.createUserWithEmailAndPassword(email, password); ``` - Rather than signIn, we using createUser so it prompt to create new user. - Firebase also has feature which there is same user using same email address will cancel the process of registration. - This cancellation also work when the user password doesn't meet standard of strong password, like less than 8 character. After this, the simple register page will like this: <center> <img src="https://raw.githubusercontent.com/aru1702/images/master/ntust-documentation/08-06.JPG" alt="img-06"> </center> </br> Now our login and register page have been created and we can test them by using `ionic serve`. Next, if we want to test it into Firebase hosting, we can deploy it. | Check | Things we need | |---|---| |✔| Create Ionic 4 project, blank page also work. | |✔| Install the angular service worker into the project. | |✔| Initialize the pages, include login and register. | |✔| Use Firebase account for authentication service, we may register first if not have one. | |✔| Install the firebase angular for PWA. | |✔| Coding the web app. | || Deploy! or run it locally works as well. | ### 5. Deploy! Let's try the web app with local ionic `ionic serve` We can use inspect element (in Chrome with CTRL+SHIFT+I) to check console: 1. Login if no user is detected <center> <img src="https://raw.githubusercontent.com/aru1702/images/master/ntust-documentation/08-07.JPG" alt="img-07"> </center> </br> 2. Register <center> <img src="https://raw.githubusercontent.com/aru1702/images/master/ntust-documentation/08-08.JPG" alt="img-08"> </center> </br> 3. Register another user with same email <center> <img src="https://raw.githubusercontent.com/aru1702/images/master/ntust-documentation/08-09.JPG" alt="img-09"> </center> </br> 4. Login with registered user <center> <img src="https://raw.githubusercontent.com/aru1702/images/master/ntust-documentation/08-10.JPG" alt="img-10"> </center> </br> --- ## References - Youtube - Firebase + Ionic 4 Login and Registration (https://www.youtube.com/watch?v=Q8zcieAWn3g) - Firebase Official Website (https://firebase.google.com/) - Async Await in TypeScript (https://basarat.gitbooks.io/typescript/docs/async-await.html) ###### tags: `pre-intern report`