ทำระบบ 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
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 ก่อน
กด “เพิ่มโครงการ” และใส่ชื่อโครงการเราลงไป อะไรก็ได้
จากนั้นให้กดปุ่ม “เพิ่ม Firebase ไปที่เว็บแอปของคุณ”
จะปรากฎหน้าต่างใหม่ที่มีค่า config มาให้เราเอาใส่ในพารามิเตอร์ firebaseConfig
ใช้งาน Authentication ด้วย Email/Password
ต่อไปเราจะเปิดการใช้งาน Authentication ด้วย Email/Password ให้เข้าไปที่หัวข้อ “Authentication” เลือก “วิธีการลงชื่อเข้าใช้” และเลือก “อีเมล/รหัสผ่าน” ให้เปิดใช้งาน
สร้าง 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 เพื่อดูว่าข้อมูลมาจริงไหม
ถ้ามาแล้วให้เช็คในส่วนของ Database ด้วยว่ามีการสร้างข้อมูลเกิดขึ้นหรือไม่ โดยข้อมูลที่อยู่ใน Database มาจาก Function ที่อยู่ใน app.service.ts ชื่อว่า updateUserData()
หมายเหตุ: หลังจากเราสมัครสมาชิกเรียบร้อยแล้ว มันจะ 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 ด้วยนะครับ
[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 ใหม่ดูว่า ข้อมูลเข้าจริงไหม แต่อย่าลืมสร้าง “คอลเล็กชัน”
จบแล้วครับกับการใช้งาน Firebase บน Angular 4 ยาวสุดๆ และสุดท้ายนี้หวังว่าบทความนี้จะเป็นประโยชน์ต่อผู้พัฒนาทุกท่านครับ :)