ทำระบบ Login ด้วย Angular 4 + Firebase

บทความนี้ผมจะไม่ขออธิบายระเอียดมากนักเนื่องจากมีโค้ดค่อนข้างเยอะ สิ่งที่มีก่อนเริ่มเลยให้ติดตั้ง Node.js ก่อนและควรศึกษาเรื่อง Node.js มาก่อนไม่งั้นจะไม่เข้าใจ เมื่อเราติดตั้ง Node.js แล้วให้เรารันคำสั่ง

npm install -g @angular/cli

เพื่อใช้งานสำหรับสร้าง Project Angular 4 จากนั้นให้รันคำสั่งต่อมา

ng new angular4-firebase

เป็นคำสั่งสร้าง Project ของ Angular 4 โดย ng new ตามด้วยชื่อ Project ไม่จำเป็นต้องชื่อตามก็ได้ แล้วแต่สะดวกเลย เมื่อสร้างเสร็จให้เข้า Folder Project นั้น

cd angular4-firebase

เนื่องจาก Angular เพียวๆ มันไม่สวย เลยเพื่ม Bootstrap 4 กับ JQuery เข้าไป

npm install bootstrap@4.0.0-beta.2 jquery --save

และ Popper.js ด้วย ไม่งั้นเวลาเรียกใช้ Bootstrap จะถามหา

npm install popper.js — save

วิธีเรียกใช้ Bootstrap กับ JQuery ให้เราเปิดไฟล์ .angular-cli.json จะเจอข้อมูลแบบ json ให้เพิ่มโค้ดในส่วนของ “styles” และ “script” ดังนี้

“styles”: [
“styles.css”,
“../node_modules/bootstrap/dist/css/bootstrap.min.css”
],
“scripts”: [
“../node_modules/jquery/dist/jquery.slim.min.js”,
“../node_modules/popper.js/dist/umd/popper.min.js”,
“../node_modules/bootstrap/dist/js/bootstrap.min.js”
],

จากนั้นทดสอบรัน Angular ดู

ng serve
ทดสอบ Angular ด้วย ng serve

URL เริ่มต้นในการเข้าเว็บไซต์คือ http://localhost:4200/

สร้าง Component

ต่อไปเราจะทำการตกแต่งหน้าตาเว็บไซต์เราก่อน เริ่มด้วยการสร้าง Component ด้วยกัน 5 Component ได้แก่

  • HomeComponent
ng g component components\home
  • LoginComponent
ng g component components\login
  • NavbarComponent
ng g component components\navbar
  • ProfileComponent
ng g component components\profile
  • SignupComponent
ng g component components\signup

ส่วนหน้า Home กับ Profile เราจะไม่ขอแต่งนะครับ ต่อไปจะเป็นการนำ Component ต่างๆ มาใช้กันผ่าน app.component.html และตั้งค่า Router ให้สามารถลิ้งไปมากันได้

[Project]\src\app\app.component.html แก้ไข
<app-navbar></app-navbar>
<main>
<div class="container">
<router-outlet></router-outlet>
</div>
</main>
[Project]\src\app\app.component.cssแก้ไข
main {
padding-top: 80px;
}
[Project]\src\app\app.module.tsแก้ไข
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
// Component
import { AppComponent } from './app.component';
import { HomeComponent } from './components/home/home.component';
import { LoginComponent } from './components/login/login.component';
import { NavbarComponent } from './components/navbar/navbar.component';
import { ProfileComponent } from './components/profile/profile.component';
import { SignupComponent } from './components/signup/signup.component';
// Routes
export const router: Routes = [
{ path: '', component: HomeComponent },
{ path: 'login', component: LoginComponent },
{ path: 'signup', component: SignupComponent },
{ path: 'profile', component: ProfileComponent }
]
@NgModule({
declarations: [
AppComponent,
HomeComponent,
LoginComponent,
NavbarComponent,
ProfileComponent,
SignupComponent
],
imports: [
BrowserModule,
RouterModule.forRoot(router)
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

พอเราตั้งค่า route เสร็จแล้วให้กลับไปเพิ่มโค้ดในส่วนของ navbar, login และ signup ใหม่ ให้สามารถลิ้งไปมาได้

[Project]\src\app\components\navbar\navbar.component.html แก้ไข
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<a class="navbar-brand text-white" [routerLink]="['/']">
Angular 4 Firebase
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
</ul>
<ul class="navbar-nav">
<li>
<a class="nav-link" [routerLink]="['/']">หน้าแรก</a>
</li>
<li>
<a class="nav-link" [routerLink]="['/login']">เข้าสู่ระบบ</a>
</li>
<li>
<a class="nav-link" [routerLink]="['/profile']">โปรไฟล์</a>
</li>
<li>
<a class="nav-link">ออกจากระบบ</a>
</li>
</ul>
</div>
</nav>
[Project]\src\app\components\login\login.component.html แก้ไข
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header text-center text-white bg-dark">
เข้าสู่ระบบ
</div>
<div class="card-body">
<form>
<div class="form-group row">
<label class="col-sm-3 col-form-label">Email</label>
<div class="col-sm-9">
<input type="email" class="form-control">
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">Password</label>
<div class="col-sm-9">
<input type="password" class="form-control">
</div>
</div>
<div class="row">
<div class="col-6 text-left">
<a class="text-muted" [routerLink]="['/signup']">
สมัครสมาชิกใหม่ ?
</a>
</div>
<div class="col-6 text-right">
<button type="submit" class="btn btn-primary">
<i class="fa fa-lock" aria-hidden="true"></i>
เข้าสู่ระบบ
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
[Project]\src\app\components\signup\signup.component.html แก้ไข
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header text-center text-white bg-dark">
สมัครสมาชิก
</div>
<div class="card-body">
<form>
<div class="form-group row">
<label class="col-sm-3 col-form-label">Email</label>
<div class="col-sm-9">
<input type="email" class="form-control">
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">Password</label>
<div class="col-sm-9">
<input type="password" class="form-control">
</div>
</div>
<div class="row">
<div class="col-6 text-left">
<a class="text-muted" [routerLink]="['/login']">
เข้าสู่ระบบ
</a>
</div>
<div class="col-6 text-right">
<button type="submit" class="btn btn-primary">
<i class="fa fa-lock" aria-hidden="true"></i>
สมัครสมาชิก
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>

ให้เราลองเล่นดูว่ามันลิ้งกันไปมาได้ไหม

ทดสอบการเชื่อมต่อหน้าแต่ละหน้า

ติดตั้ง Firebase และ AngularFire2

ให้เราลง Firebase และ AngularFire2 ด้วย Node.js

npm install firebase angularfire2 --save

ตั้งค่า Firebase ใน AppModule

ต่อไปเราจะทำการตั้งค่า Firebase ใน Project เรา

[Project]\src\app\app.module.tsแก้ไข
ค่า config ไปใส่ใน app.module.tsimport { BrowserModule } from ‘@angular/platform-browser’;
import { NgModule } from ‘@angular/core’;
import { RouterModule, Routes } from ‘@angular/router’;
import { FormsModule, ReactiveFormsModule } from ‘@angular/forms’;
import { HttpModule } from ‘@angular/http’;
// Component
import { AppComponent } from ‘./app.component’;
import { HomeComponent } from ‘./components/home/home.component’;
import { LoginComponent } from ‘./components/login/login.component’;
import { NavbarComponent } from ‘./components/navbar/navbar.component’;
import { ProfileComponent } from ‘./components/profile/profile.component’;
import { SignupComponent } from ‘./components/signup/signup.component’;
// Firebase
import { AngularFireModule } from ‘angularfire2’;
import { AngularFireAuthModule } from ‘angularfire2/auth’;
import { AngularFireDatabase, AngularFireObject } from 'angularfire2/database';
import { AngularFirestoreModule } from ‘angularfire2/firestore’;
// Routes
export const router: Routes = [
{ path: ‘’, component: HomeComponent },
{ path: ‘login’, component: LoginComponent },
{ path: ‘signup’, component: SignupComponent },
{ path: ‘profile’, component: ProfileComponent }
]
// Config Firebase
export const firebaseConfig = {
apiKey: “”,
authDomain: “”,
databaseURL: “”,
projectId: “”,
storageBucket: “”,
messagingSenderId: “”
};
@NgModule({
declarations: [
AppComponent,
HomeComponent,
LoginComponent,
NavbarComponent,
ProfileComponent,
SignupComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpModule,
RouterModule.forRoot(router),
AngularFireAuthModule,
AngularFireModule.initializeApp(firebaseConfig)
],
providers: [AngularFireDatabase],
bootstrap: [AppComponent]
})
export class AppModule { }

ตั้งค่า Firebase Config

จากโค้ดด้านบน firebaseConfig ยังไม่มีเราจะต้องสร้าง Project ใน https://console.firebase.google.com ก่อน

https://console.firebase.google.com

กด “เพิ่มโครงการ” และใส่ชื่อโครงการเราลงไป อะไรก็ได้

สร้างโครงการใหม่

จากนั้นให้กดปุ่ม “เพิ่ม Firebase ไปที่เว็บแอปของคุณ”

สร้าง config firebase

จะปรากฎหน้าต่างใหม่ที่มีค่า config มาให้เราเอาใส่ในพารามิเตอร์ firebaseConfig

ค่า config ไปใส่ใน app.module.ts

ใช้งาน Authentication ด้วย Email/Password

ต่อไปเราจะเปิดการใช้งาน Authentication ด้วย Email/Password ให้เข้าไปที่หัวข้อ “Authentication” เลือก “วิธีการลงชื่อเข้าใช้” และเลือก “อีเมล/รหัสผ่าน” ให้เปิดใช้งาน

เปิดใช้งาน Email/Password

สร้าง Service และ Guard

สร้าง Service เพื่อเป็นเส้นทางการเรียกใช้ Firebase และ Guard สำหรับตรวจสอบว่าเรา Login อยู่หรือไม่

ng g service services/auth
ng g guard guards/auth
[Project]\src\app\guards\auth.guard.tsแก้ไข
import { Injectable } from ‘@angular/core’;
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from ‘@angular/router’;
import { Observable } from ‘rxjs/Observable’;
import { AngularFireAuth } from ‘angularfire2/auth’;
import ‘rxjs/add/operator/do’;
import ‘rxjs/add/operator/map’;
import ‘rxjs/add/operator/take’;
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private afAuth: AngularFireAuth, private router: Router) { }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | boolean {
return this.afAuth.authState
.take(1)
.map(user => !!user)
.do(loggedIn => {
if (!loggedIn) {
this.router.navigate([‘/login’]);
}
})
}
}

เรากำหนดเงื่อนไขไว้ใน Guard ว่าถ้ายังไม่ได้ Login ให้ไปหน้า Login ก่อนเสมอ

[Project]\src\app\services\auth.service.tsแก้ไข
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { AngularFireDatabase, AngularFireObject } from 'angularfire2/database';
import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';
@Injectable()
export class AuthService {
authState: any = null;
userRef: AngularFireObject<any>;
constructor(private afAuth: AngularFireAuth,
private db: AngularFireDatabase,
private router: Router) {
this.afAuth.authState.subscribe((auth) => {
this.authState = auth
});
}
get authenticated(): boolean {
return this.authState !== null;
}
get currentUser(): any {
return this.authenticated ? this.authState : null;
}
get currentUserObservable(): any {
return this.afAuth.authState
}
get currentUserId(): string {
return this.authenticated ? this.authState.uid : '';
}
get currentUserAnonymous(): boolean {
return this.authenticated ? this.authState.isAnonymous : false
}
get currentUserDisplayName(): string {
if (!this.authState) {
return 'Guest'
} else if (this.currentUserAnonymous) {
return 'Anonymous'
} else {
return this.authState['displayName'] || 'User without a Name'
}
}
githubLogin() {
const provider = new firebase.auth.GithubAuthProvider()
return this.socialSignIn(provider);
}
googleLogin() {
const provider = new firebase.auth.GoogleAuthProvider()
return this.socialSignIn(provider);
}
facebookLogin() {
const provider = new firebase.auth.FacebookAuthProvider()
return this.socialSignIn(provider);
}
twitterLogin() {
const provider = new firebase.auth.TwitterAuthProvider()
return this.socialSignIn(provider);
}
private socialSignIn(provider) {
return this.afAuth.auth.signInWithPopup(provider)
.then((credential) => {
console.log(credential.user);
this.authState = credential.user
this.updateUserData()
this.router.navigate(['/'])
})
.catch(error => console.log(error));
}
anonymousLogin() {
return this.afAuth.auth.signInAnonymously()
.then((user) => {
this.authState = user
this.router.navigate(['/'])
})
.catch(error => console.log(error));
}
emailSignUp(email: string, password: string) {
return this.afAuth.auth.createUserWithEmailAndPassword(email, password)
.then((user) => {
this.authState = user
this.updateUserData()
this.router.navigate(['/'])
})
.catch(error => console.log(error));
}
emailLogin(email: string, password: string) {
return this.afAuth.auth.signInWithEmailAndPassword(email, password)
.then((user) => {
this.authState = user
this.updateUserData()
this.router.navigate(['/'])
})
.catch(error => console.log(error));
}
resetPassword(email: string) {
const fbAuth = firebase.auth();
return fbAuth.sendPasswordResetEmail(email)
.then(() => console.log('email sent'))
.catch((error) => console.log(error))
}
getCurrentLoggedIn() {
this.afAuth.authState.subscribe(auth => {
if (auth) {
this.router.navigate(['/'])
}
});
}
signOut(): void {
this.afAuth.auth.signOut();
this.router.navigate(['/'])
}
private updateUserData(): void {
const path = `users/${this.currentUserId}`; // Endpoint on firebase
const userRef: AngularFireObject<any> = this.db.object(path);
const data = {
email: this.authState.email,
name: this.authState.displayName
}
userRef.update(data)
.catch(error => console.log(error));
}
}

โดยโค้ดนี้จะประกอบไปด้วยการ Login ต่างๆ ของ Social ไว้หมดเลย และยังมีคำสั่ง Update Database ของ Firebase กับ Sign Out พร้อมอยู่แล้ว ต่อไปเราจะเรียก Service นี้ในการติดต่อกับ Firebase หล่ะ

เราต้องมาอัพเดท app.module.ts ก่อนเพราะการเรียกใช้เจ้า service และ guard ได้นั้นต้องมากำหนดในไฟล์นี้

[Project]\src\app\services\auth.service.tsแก้ไข
import { BrowserModule } from ‘@angular/platform-browser’;
import { NgModule } from ‘@angular/core’;
import { RouterModule, Routes } from ‘@angular/router’;
import { FormsModule, ReactiveFormsModule } from ‘@angular/forms’;
import { HttpModule } from ‘@angular/http’;
// Component
import { AppComponent } from ‘./app.component’;
import { HomeComponent } from ‘./components/home/home.component’;
import { LoginComponent } from ‘./components/login/login.component’;
import { NavbarComponent } from ‘./components/navbar/navbar.component’;
import { ProfileComponent } from ‘./components/profile/profile.component’;
import { SignupComponent } from ‘./components/signup/signup.component’;
// Firebase
import { AngularFireModule } from ‘angularfire2’;
import { AngularFireAuthModule } from ‘angularfire2/auth’;
import { AngularFireDatabase, AngularFireObject } from 'angularfire2/database';
import { AngularFirestoreModule } from ‘angularfire2/firestore’;
// Service
import { AuthService } from ‘./services/auth.service’;
// Guard
import { AuthGuard } from ‘./guards/auth.guard’;
// Routes
export const router: Routes = [
{ path: ‘’, component: HomeComponent },
{ path: ‘login’, component: LoginComponent },
{ path: ‘signup’, component: SignupComponent },
{ path: ‘profile’, component: ProfileComponent, canActivate: [AuthGuard] }
]
// Config Firebase
export const firebaseConfig = {
apiKey: “xxxxxxxx”,
authDomain: “xxxxxxxx”,
databaseURL: “xxxxxxxx",
projectId: “xxxxxxxx”,
storageBucket: “xxxxxxxx”,
messagingSenderId: “xxxxxxxx”
};
@NgModule({
declarations: [
AppComponent,
HomeComponent,
LoginComponent,
NavbarComponent,
ProfileComponent,
SignupComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpModule,
RouterModule.forRoot(router),
AngularFireAuthModule,
AngularFireModule.initializeApp(firebaseConfig)
],
providers: [AuthService, AngularFireDatabase, AuthGuard],
bootstrap: [AppComponent]
})
export class AppModule { }

สำหรับโค้ด canActivate: [AuthGuard] เป็นตัวกำหนดว่า หน้าไหนจะต้อง Login ก่อนเสมอถึงจะเข้าใช้งานได้

สำหรับโค้ด auth.service.ts ผมไปนำมาจาก angularfirebase สามารถดูตัวอย่างการใช้งานอย่างอื่นได้

ทำระบบสมัครสมาชิกด้วย Email/Password

ต่อไปเราจะทำการอัพเดทโค้ด signup.component.html กับ signup.component.ts

[Project]\src\app\component\signup\signup.component.htmlแก้ไข
<div class=”row justify-content-center”>
<div class=”col-md-6">
<div class=”card”>
<div class=”card-header text-center text-white bg-dark”>
สมัครสมาชิก
</div>
<div class=”card-body”>
<form [formGroup]=”userForm” (ngSubmit)=”signup()”>
<div class=”form-group row”>
<label class=”col-sm-3 col-form-label”>Email</label>
<div class=”col-sm-9">
<input type=”email” formControlName=”emailSignup” class=”form-control”>
</div>
</div>
<div class=”form-group row”>
<label class=”col-sm-3 col-form-label”>Password</label>
<div class=”col-sm-9">
<input type=”password” formControlName=”passwordSignup” class=”form-control”>
</div>
</div>
<div class=”row”>
<div class=”col-6 text-left”>
<a class=”text-muted” [routerLink]=”[‘/login’]”>
เข้าสู่ระบบ
</a>
</div>
<div class=”col-6 text-right”>
<button type=”submit” class=”btn btn-primary”>
<i class=”fa fa-lock” aria-hidden=”true”></i>
สมัครสมาชิก
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
[Project]\src\app\component\signup\signup.component.tsแก้ไข
import { Component, OnInit } from ‘@angular/core’;
import { AuthService } from “../../services/auth.service”;
import { ReactiveFormsModule, FormGroup, FormControl, FormBuilder, Validators } from ‘@angular/forms’;
@Component({
selector: ‘app-signup’,
templateUrl: ‘./signup.component.html’,
styleUrls: [‘./signup.component.css’]
})
export class SignupComponent implements OnInit {
userForm: FormGroup;
emailSignup: string;
passwordSignup: string;
constructor(private fb: FormBuilder, private auth: AuthService) { }
ngOnInit() {
this.buildForm();
}
buildForm(): void {
this.userForm = new FormGroup({
emailSignup: new FormControl(‘’, [
Validators.required,
Validators.email
]),
passwordSignup: new FormControl(‘’, [
Validators.pattern(‘^(?=.*[0–9])(?=.*[a-zA-Z])([a-zA-Z0–9]+)$’),
Validators.minLength(6),
Validators.maxLength(25)
])
});
}
signup(): void {
this.auth.emailSignUp(this.userForm.value.emailSignup, this.userForm.value.passwordSignup)
}
}

จากโค้ดส่วนนี้ เรากำหนดชื่อ Form กับชื่อ Input ไว้แล้ว จากนั้นเรียกใช้ auth.service.ts โดยการ import เข้ามาแล้วสร้างตัวแปรไว้ใน Constructor แปลว่าทุกครั้งที่เข้าหน้านี้จะเป็นการเรียก auth.service.ts เสมอ จากนั้นเราก็เรียกใช้ Function emailSignUp() ได้เลย โดยผมจะสร้าง Function ใหม่ใน SignupComponent อีกที แล้วลองทดสอบดูว่ามันสร้าง Users จริงไหม

ทดสอบสมัครสมาชิก

ให้เราเข้า https://console.firebase.google.com เพื่อดูว่าข้อมูลมาจริงไหม

ข้อมูลการสมัครสมาชิก 1

ถ้ามาแล้วให้เช็คในส่วนของ Database ด้วยว่ามีการสร้างข้อมูลเกิดขึ้นหรือไม่ โดยข้อมูลที่อยู่ใน Database มาจาก Function ที่อยู่ใน app.service.ts ชื่อว่า updateUserData()

ข้อมูลใน Database

หมายเหตุ: หลังจากเราสมัครสมาชิกเรียบร้อยแล้ว มันจะ Login ให้เราอัตโนมัติ ดังนั้นเราจำเป็นต้องทำปุ่ม “ออกจากระบบ” โดยใช้ Function signOut() ใน auth.service.ts ก่อน

ทำระบบออกจากระบบ Sign Out

ต่อไปเราจะทำการอัพเดทโค้ด navbar.component.html กับ navbar.component.ts ส่วนเหตุผลที่ทำระบบ Sign Out ก่อนเพราะเมื่อเราสมัครเสร็จมันจะ Login ให้เราเลย

[Project]\src\app\component\navbar\navbar.component.htmlแก้ไข
<nav class=”navbar navbar-expand-md navbar-dark bg-dark fixed-top”>
<a class=”navbar-brand text-white” [routerLink]=”[‘/’]”>
Angular 4 Firebase
</a>
<button class=”navbar-toggler” type=”button” data-toggle=”collapse” data-target=”#navbarsExampleDefault” aria-controls=”navbarsExampleDefault”
aria-expanded=”false” aria-label=”Toggle navigation”>
<span class=”navbar-toggler-icon”></span>
</button>
<div class=”collapse navbar-collapse” id=”navbarsExampleDefault”>
<ul class=”navbar-nav mr-auto”>
</ul>
<ul class=”navbar-nav”>
<li>
<a class=”nav-link” [routerLink]=”[‘/’]”> หน้าแรก</a>
</li>
<li *ngIf=”!auth.authenticated”>
<a class=”nav-link” [routerLink]=”[‘/login’]”>เข้าสู่ระบบ</a>
</li>
<li *ngIf=”auth.authenticated”>
<a class=”nav-link” [routerLink]=”[‘/profile’]”>Profile</a>
</li>
<li *ngIf=”auth.authenticated”>
<a class=”nav-link” (click)=”this.auth.signOut()”>ออกจากระบบ</a>
</li>
</ul>
</div>
</nav>
[Project]\src\app\component\navbar\navbar.component.tsแก้ไข
import { Component, OnInit } from ‘@angular/core’;
import { Router } from ‘@angular/router’;
import { AuthService } from “../../services/auth.service”;
@Component({
selector: ‘app-navbar’,
templateUrl: ‘./navbar.component.html’,
styleUrls: [‘./navbar.component.css’]
})
export class NavbarComponent implements OnInit {
constructor(
private router:Router,
private auth: AuthService
) { }
ngOnInit() {
}
}

ให้เราลอง Login ดูคราวนี้แถบเมนู navbar จะเหลือแค่ “หน้าแรก” “โปรไฟล์” และ “ออกจากระบบ” เป็นผลมาจากเรากำหนดเงื่อนไขใน navbar.component.html ว่า

*ngIf=”!auth.authenticated”

ถ้าไม่ได้ Login อยู่ให้ซ่อน เมนูนี้ กลับกัน

*ngIf=”auth.authenticated”

ถ้า Login ก็ให้แสดงออกมา

ทำระบบ Login ด้วย Email/Password

ต่อไปเราจะทำการอัพเดทโค้ด login.component.html กับ login.component.ts

[Project]\src\app\component\login\login.component.htmlแก้ไข
<div class=”row justify-content-center”>
<div class=”col-md-6">
<div class=”card”>
<div class=”card-header text-center text-white bg-dark”>
เข้าสู่ระบบ
</div>
<div class=”card-body”>
<form [formGroup]=”loginForm” (ngSubmit)=”login()”>
<div class=”form-group row”>
<label class=”col-sm-3 col-form-label”>Email</label>
<div class=”col-sm-9">
<input type=”email” formControlName=”email” class=”form-control”>
</div>
</div>
<div class=”form-group row”>
<label class=”col-sm-3 col-form-label”>Password</label>
<div class=”col-sm-9">
<input type=”password” formControlName=”password” class=”form-control”>
</div>
</div>
<div class=”row”>
<div class=”col-6 text-left”>
<a class=”text-muted” [routerLink]=”[‘/signup’]”>
สมัครสมาชิกใหม่ ?
</a>
</div>
<div class=”col-6 text-right”>
<button type=”submit” class=”btn btn-primary”>
<i class=”fa fa-lock” aria-hidden=”true”></i>
เข้าสู่ระบบ
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
[Project]\src\app\component\login\login.component.tsแก้ไข
import { Component, OnInit } from ‘@angular/core’;
import { AuthService } from “../../services/auth.service”;
import { ReactiveFormsModule, FormGroup, FormBuilder, FormControl, Validators } from ‘@angular/forms’;
import { Router } from ‘@angular/router’;
@Component({
selector: ‘app-login’,
templateUrl: ‘./login.component.html’,
styleUrls: [‘./login.component.css’]
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
constructor(
private fb: FormBuilder,
private auth: AuthService,
private router: Router
) {
auth.getCurrentLoggedIn();
}
ngOnInit() {
this.buildForm();
}
buildForm(): void {
this.loginForm = new FormGroup({
email: new FormControl(‘’, [
Validators.required,
Validators.email
]),
password: new FormControl(‘’, [
Validators.pattern(‘^(?=.*[0–9])(?=.*[a-zA-Z])([a-zA-Z0–9]+)$’),
Validators.minLength(6),
Validators.maxLength(25)
])
});
}
login(): void {
this.auth.emailLogin(this.loginForm.value.email, this.loginForm.value.password)
}
}

ลอง Login ดูว่าได้ไหม และทดสอบด้วยว่าถ้ากลับมาหน้า Login แล้วมันยังให้เข้าอยู่ไหม โดยโค้ดที่อยู่ใน Constructor

auth.getCurrentLoggedIn();

เป็นตัว Check ว่าเรากำลัง Login อยู่หรือไม่ ถ้าใครอยากไม่ให้เข้าหน้าไหนแล้วจาก Login แล้วก็นำไปวางไว้ได้เลย แต่อย่าลืม Import AuthService อย่าลืมไปใส่หน้า signup ด้วยนะครับ

ทดสอบ Login
ทดสอบ Login
[Project]\src\app\component\signup\signup.component.tsแก้ไข
import { Component, OnInit } from ‘@angular/core’;
import { AuthService } from “../../services/auth.service”;
import { ReactiveFormsModule, FormGroup, FormControl, FormBuilder, Validators } from ‘@angular/forms’;
@Component({
selector: ‘app-signup’,
templateUrl: ‘./signup.component.html’,
styleUrls: [‘./signup.component.css’]
})
export class SignupComponent implements OnInit {
userForm: FormGroup;
emailSignup: string;
passwordSignup: string;
constructor(private fb: FormBuilder, private auth: AuthService) {
auth.getCurrentLoggedIn();
}
ngOnInit() {
this.buildForm();
}
buildForm(): void {
this.userForm = new FormGroup({
emailSignup: new FormControl(‘’, [
Validators.required,
Validators.email
]),
passwordSignup: new FormControl(‘’, [
Validators.pattern(‘^(?=.*[0–9])(?=.*[a-zA-Z])([a-zA-Z0–9]+)$’),
Validators.minLength(6),
Validators.maxLength(25)
])
});
}
signup(): void {
this.auth.emailSignUp(this.userForm.value.emailSignup, this.userForm.value.passwordSignup)
}
}

เปลี่ยนฐานข้อมูลเป็น Cloud Firestore

เราจะเปลี่ยนฐานข้อมูลของ Firebase แบบเก่าเป็น Cloud Firestore (รุ่นเบต้า) นั้นง่ายมาก โดยเราจะเพิ่มโค้ดในส่วนของ app.module.ts กับ auth.service.ts

[Project]\src\app\app.module.tsแก้ไข
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpModule,
RouterModule.forRoot(router),
AngularFireAuthModule,
AngularFireModule.initializeApp(firebaseConfig),
AngularFirestoreModule <--- เพิ่ม
],

จากโค้ดก่อนหน้านี้เราได้ Import AngularFirestoreModule มาก่อนแล้ว เราแค่ทำการเพิ่มเข้าไปใน Project เราได้เลย ต่อมา

[Project]\src\app\services\auth.serivce.tsแก้ไข
constructor(
private afAuth: AngularFireAuth,
private db: AngularFireDatabase,
private router: Router,
private afs: AngularFirestore <-- เพิ่ม
) {
this.afAuth.authState.subscribe((auth) => {
this.authState = auth
});
}

ในส่วนของ Constructor เราจะเพิ่ม AngularFirestore เข้ามา โดยเรา Import เข้ามาก่อนหน้านี้แล้ว

addUserData() {
this.afs.collection(‘users’).add({‘email’: this.authState.email});
}

เพิ่ม Function ใหม่ addUserData เข้าไป จากนั้นแก้ไข Function emailSignUp

emailSignUp(email: string, password: string) {
return this.afAuth.auth.createUserWithEmailAndPassword(email, password)
.then((user) => {
this.authState = user
this.addUserData(); <-- เพิ่ม ก่อนหน้านี้จะมี Function updateUserData
this.router.navigate([‘/’])
})
.catch(error => console.log(error));
}

จากนั้นลองสร้าง Email/Password ใหม่ดูว่า ข้อมูลเข้าจริงไหม แต่อย่าลืมสร้าง “คอลเล็กชัน”

สร้าง Email/Password ใหม่
ตรวจสอบข้อมูลหลังจากสร้าง Email/Password ใหม่ใน Cloud Firestore

จบแล้วครับกับการใช้งาน Firebase บน Angular 4 ยาวสุดๆ และสุดท้ายนี้หวังว่าบทความนี้จะเป็นประโยชน์ต่อผู้พัฒนาทุกท่านครับ :)