ใช้งาน Route Guard กำหนด Authorized ให้ Route ใน Angular ตอนที่ 8

เขียนเมื่อ 6 ปีก่อน โดย Ninenik Narkdee
angular router canactivatechild canactivate

คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ angular router canactivatechild canactivate

ดูแล้ว 16,783 ครั้ง


เนื้อหาในตอนต่อไปนี้ จะมาดูในเรื่องของการตรวจสอบสิทธิ์การเข้าใช้งาน route path ยกตัวอย่างเช่น
เรามี route path ที่ จำกัดสิทธิ์เฉพาะผู้ใช้ อย่างหน้าจัดการของส่วน Admin เป็นต้น โดยเมื่อมีการเรียก
path ที่ถูกจำกัดสิทธิ์ ก่อนที่จะแสดง path นั้น จะมีการตรวจสอบว่า ผู้ใช้นั้นได้สิทธิ์ในการเข้าถึงแล้วหรือไม่
    ในเนื้อหา จะไม่ได้ลงรายละเอียดถึงขั้นตอนการได้สิทธิ์การเข้าถึง แต่จะสมมติผลลัพธ๋ที่ได้อย่างง่าย
เพื่อให้เห็นแนวทางในการใช้งาน route guard

เหตุผลหรือเงื่อนไขที่พอเป็นไปได้ในการใช้งาน route guard

 
- ผู้ใช้อาจจะไม่ได้รับสิทธิ์ในการเข้าถึง route path ของ component นั้นๆ
- หรือผู้ใช้จำเป็นต้องมีการล็อกอินเพื่อเข้าใช้งานก่อน
- หรือมีการดึงข้อมูลบางอย่างก่อนที่จะแสดง component นั้น อย่างที่เราใช้ resole ในเนื้อหาที่ผ่านมา
- หรือต้องยืนยันการบันทึกข้อมูลที่มีการเปลี่ยนแปลง ก่อนออกจากหน้านั้นๆ
- หรือต้องการให้ผู้ใช้ยืนยัน ว่าจะไม่มีการบันทึกการเปลี่ยนแปลงข้อมูล ก่อนออกจากหน้านั้น 
 
เพื่อจัดการกับเงื่อนไขที่อาจจะเป็นไปได้ข้างต้น เราเพิ่มการกำหนด guard เข้าไปในส่วนของการตั้งค่า route path
ค่าที่ได้จากการกำหนด route guard จะใช้เป็นตัวกำหนดการแสดงของ router โดย
 
    ถ้ามีค่าเป็น true การเปลี่ยนแปลง route path ก็จะดำเนินการต่อ ไปยัง path ที่ต้องการ
    ถ้ามีค่าเป็น false จะไม่มีการเปลี่ยนแปลง route path หรืออยู่ที่เดิม
 
อย่างไรก็ตาม กรณีคืนค่าเป็น false เราสามารถกำหนดให้ router ลิ้งค์ยังไปหน้าต่างๆ ในแต่ละขั้นตอน
ได้ตามความเหมาะสม
    การคืนค่าของ guard อาจจะเกิดขั้นในทันที (synchronously) หรือเกิดขึ้นตามมากายหลัง (asynchronously) ก็ได้
กรณีเกิดขึ้นภายหลังก็เช่น guard อาจจะมีการถามเพื่อยืนยันจากผู้ใช้ หรือ อาจจะบันทึกข้อมูลไปยัง server ก่อน
หรือแม้แต่ กำลังทำการดึงข้อมูลจาก server อยู่ เหล่านี้เป็นต้น ก็ทำให้การคืนค่าของ guard เกิดขึ้นภายหลัง และด้วยรูป
แบบข้างต้น ค่าที่ return กลับมาอาจจะเป็นได้ทั้ง Observable<boolean> หรือ Promise<boolean> ดังนั้นผู้ใช้จะต้อง
รอจนกว่า Observable จะได้ค่าเป็น true หรือ false ก่อน 
 

Router สามารถใช้งาน Guard Interface ต่อไปนี้ ตามรูปแบบการทำงาน

 
    CanActivate สำหรับเป็นตัวกลางพิจารณาการเข้าถึง route path
    CanActivateChild สำหรับเป็นตัวกลางพิจารณาการเข้าถึง route path ย่อย
    CanDeactivate สำหรับเป็นตัวกลางพิจารณาการออกจาก route path ปัจจุบัน
    Resolve ดึงข้อมูลที่ต้องการก่อนที่เนื้อหาใน route path จะแสดง 
    CanLoad สำหรับเป็นตัวกลางพิจารณาการเข้าถึง route path โดยจะมีการโหลด module ของ route path ที่จะเข้าใช้งาน ภายหลัง
 
สำหรับเนื้อหาเกี่ยวกับการใช้งาน resole interface ดึงข้อมูลก่อนที่เนื้อหาใน route path จะแสดง เรามีตัวอย่าง
ไปแล้วในบทความตามลิ้งค์ด้านล่าง สามารถย้อนไปทบทวนได้
    ใช้งาน Observable paramMap และ component reuse ใน Angular ตอนที่ 6 http://niik.in/846 
 
เราสามารถใช้งาน Guard ในแต่ละระดับของการกำหนด routing ได้ โดยลำดับการตรวจสอบของ router จะดูในส่วนของ
CanDeactivate และ CanActivateChild guard ก่อน เริ่มจากด้านในที่สุดของ route ย่อยไล่ออกมายังด้านนอกสุด
จากนั้นก็จะตรวจสอบในส่วนของ CanActivate guard จาก route นอกสุดไล่ลงไปตาม route ย่อยด้านใน และถ้าในกรณีมีการ
โหลดแบบ asynchronously ส่วนของ CanLoad guard จะตรวจสอบก่อนที่ module จะถูกโหลด
 
ตอนนี้ได้อธิบายการทำงาน หลักการใช้งานคร่าวๆ ไปแล้ว ต่อไปจะเป็นส่วนวิธีการใช้งาน จะขอไปแบบเร็ว และข้ามในบาง
ตัวอย่างของโค้ดไป เพื่อไม่ให้เนื้อหายาวจนเกินไป 
    เริ่มต้น เราจะสร้างหน้า admin ขึ้นมา เพื่อใช้ในการจัดการ user และ product ให้สอดคล้องกับตัวอย่าง ที่ผ่านๆ
มาด้วยคำสั่งต่อไปนี้ตามลำดับ
 
C:\projects\simplerouter>ng g module admin --routing
C:\projects\simplerouter>ng g c admin/admin --flat
C:\projects\simplerouter>ng g c admin/admin-center --flat
C:\projects\simplerouter>ng g c admin/manage-users --flat
C:\projects\simplerouter>ng g c admin/manage-products --flat
 
ต่อไปสร้างในส่วนของ login ให้สำหรับ admin เราจะแยกเป็น module เลย เพื่อจะได้เห็นเป็นสัดส่วนชัดเจน เช่นเดียว
กับ module อื่นๆ พร้อมกับสร้าง component หน้าล็อกอินด้วย โดยใช้คำสั่ง ดังนี้
 
C:\projects\simplerouter>ng g module login --routing
C:\projects\simplerouter>ng g c login/login --flat
 
ตอนนี้เราเตรียม module และ component ต่างๆ ไว้แล้ว จะได้ไฟล์ และโฟลเดอร์ตามรูปด้านล่าง
 
 
        

 
 
เรายังไม่สนใจในส่วนที่สร้างขึ้นมาในตอนนี้ สิ่งที่ต้องทำต่อไปคือ การสร้าง service สำหรับใช้ในการล็อกอิน และล็อกเอาท์
ในที่นี้เราจะสร้างเป็นแบบการจำลองการล็อกอินและล็อกเอาท์ และอีก service ก็คือ guard service ทำหน้าที่เหมือนเป็นด่าน
กำแพงกั้นการเข้าถึงส่วนที่เราจำกัดสิทธิ์ โดย guard service ต้องใช้งานร่วมกับ service ที่ใช้ในการล็อกอิน เพื่อเช็คว่า
ผู้ใช้นั้น ได้สิทธิ์ในการเข้าใช้งานผ่านการล็อกอินแล้วหรือไม่ เราจะใช้ชื่อ service ทั้งสองดังนี้
 
  • AuthService สำหรับเป็น Authorized Service
  • AuthGuardService สำหรับเป็น Guard Service
 
โดยทั้งสองไฟล์นี้ เราจะสร้างไว้ที่ root ของ App หรือที่เดียวกับ AppModule ไฟล์ ให้สร้างด้วยคำสั่งต่อไปนี้
 
C:\projects\simplerouter>ng g service auth
C:\projects\simplerouter>ng g service auth-guard
 
เราจะได้ไฟล์ auth.service.ts และ auth-guard.service.ts ใน root ของ App ให้ปรับโค้ดในไฟล์ ตามลำดับดังนี้
คำอธิบายการทำงานแสดงในโค้ด
 
ไฟล์ auth.service.ts
 
import { Injectable } from '@angular/core';

// import ในส่วนที่จะใช้งานกับ Observable
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/delay';

@Injectable()
export class AuthService {

  public isLoggedIn:boolean = false; // กำหนดสถานะล็อกอินเริ่มต้นเป็น false
  public redirectUrl: string; // กำหนดตัวแปรสำหรับเก็บ url ที่จะลิ้งค์ไป

  constructor() { }

  // ฟังก์ชั่นจำลองการล็อกอิน คืนค่าเป็น Observable
  login(): Observable<boolean> {
    // เมื่อล็อกอิน
    return Observable.of(true) // ให้คืนค่า true
    .delay(3000) // หลังจาก delay 3 วินาที
    .do(val => this.isLoggedIn = true); // เมื่อถึงเวลาให้กำหนดค่าสถานะเป็น true
  }
  
  // ฟังก์ชั่นจำลองการล็อกเอาท์
  logout(): void {
    // ให้ค่าสถานะล็อกอินเป็น false
    this.isLoggedIn = false;
  }  

}

การกำหนด CanActivate และ CanActivateChild


 
ไฟล์ auth-guard.service.ts
 
import { Injectable } from '@angular/core';
// import ส่วนที่จะใช้งาน guard เช่น CanActivate, CanActivateChild เป็นต้นมาใช้งาน
import {
  CanActivate, Router,
  ActivatedRouteSnapshot,
  RouterStateSnapshot,
  CanActivateChild
} from '@angular/router';
// import service ที่เช็คสถานะการล็อกอินมาใช้งาน
import { AuthService } from './auth.service';

@Injectable()
export class AuthGuardService {

  // inject AuthService และ Router 
  constructor(
    private authService: AuthService, 
    private router: Router) {}
  
  // กำนหนด guard ในส่วนของการใช้งานกับ  canActivate
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    console.log('canActivate run');
    let url: string = state.url; // เก็บ url ที่พยายามจะเข้าใช้งาน
    // จะผ่านเข้าใช้งานได้เมื่อ คืนค่าเป็น true โดยเข้าไปเช็คค่าจากคำสั่ง checkLogin()
    return this.checkLogin(url); // คืนค่าการตรวจสอบสถานะการล็อกอิน
  }

  // กำนหนด guard ในส่วนของการใช้งานกับ  canActivateChild ส่วนนี้จะใช้กับ path ของ route ย่อย
  // ถ้าเข้าผ่าน route path ย่อย guard จะเข้ามาเช็คในส่วนนี้ก่อน กลับไปเช็คในส่วนของ canActivate()
  canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    console.log('canActivateChild run');
    // จะเข้าใช้งานได้เมื่อ คืนค่าเป็น true โดยจะใช้ค่าจากการเรียกใช้คำสั่ง canActivate()
    return this.canActivate(route, state);
  }

  // ฟังก์ชั่นเช็คสถานะการล็อกอิน รับค่า url ที่ผู้ใช้พยายามจะเข้าใช้งาน
  checkLogin(url: string): boolean {
    // ถ้าตรวจสอบค่าสถานะการล็อกอินแล้วเป็น true ก็ให้คืนค่า true กลับอกไป
    if (this.authService.isLoggedIn) { return true; }
    
    // แต่ถ้ายังไม่ได้ล็อกอิน ให้เก็บ url ที่พยายามจะเข้าใช้งาน สำหรับไว้ลิ้งค์เปลี่ยนหน้า
    this.authService.redirectUrl = url; // redirectUrl เป็นตัวแปรที่อยู่ใน authService

    // ลิ้งค์ไปยังหน้าล็อกอิน เพื่อล็อกอินเข้าใช้งานก่อน
    this.router.navigate(['/login']);
    return false; // คืนค่า false กรณียังไม่ได้ล็อกอิน
  }    

}
 
ตอนนี้เราได้ service ที่ใช้สำหรับตรวจสอบการล็อกอินเข้าใช้งาน และ service สำหรับป้องกันการเข้าถึงหน้าที่
เราจำกัดสิทธิไว้แล้วเรียบร้อยแล้ว ส่วนต่อไป ก็จะเป็นหน้าล็อกอิน ที่ผู้ใช้จะถูก redirect หรือลิ้งค์กลับมาถ้ายัง
ไม่ได้ทำการล็อกอินเข้าใช้งาน สำหรับตัวอย่างการล็อกอินเข้าใช้งานของเรา จะเป็นเพียงการคลิกที่ปุ่มล็อกอิน
ก็สามารถเข้าใช้งานได้แล้ว เป็นการจำลองการทำงานเท่านั้น แต่รูปแบบสามารถนำไปประยุกต์ได้
    จากคำสั่งในตอนต้น ที่เราได้สร้าง module ,route module และ component ของหน้าล็อกอินไว้แล้ว
ให้เราปรับไฟล์ต่างๆ ตามนี้ คำอธิบายแสดงในโค้ด
 
ไฟล์ login-routing.module.ts
 
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { LoginComponent } from './login.component';
import { AuthService } from '../auth.service';

// กำหนด route path ให้กับ login component
const loginRoutes: Routes = [
  {
    path:'login',
    component:LoginComponent
  }
];

@NgModule({
  imports: [RouterModule.forChild(loginRoutes)],
  exports: [RouterModule],
  providers:[ // กำนหด providers
    AuthService // เนื่งอจากเราจะมีการใช้งาน AuthService 
  ]
})
export class LoginRoutingModule { }
 
ไฟล์ login.module.ts 
 
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { LoginRoutingModule } from './login-routing.module';
import { LoginComponent } from './login.component';

@NgModule({
  imports: [
    CommonModule,
    LoginRoutingModule
  ],
  declarations: [LoginComponent]
})
export class LoginModule { }
 
ไฟล์ login.component.html
 
<p>login works!</p>
<div>{{ loginMessage }}</div>
<form >
  <div style="width:50%;">
    <div>
      <label>Username</label>
    </div>
    <div>
      <input type="text" class="form-control" name="username" value="">
    </div>
    <div>
        <label>Password</label>
      </div>
      <div>
        <input type="password" class="form-control" name="password" value="">
      </div>  
      <br>
      <p>
        <button class="btn btn-sm btn-success" (click)="login()" type="button">Login</button>  
        <button class="btn btn-sm btn-danger" (click)="cancel()" type="button">Cancel</button>
      </p>  
  </div>
</form>
 
ส่วนของหน้าล็อกอิน เราจะสร้างฟอร์มง่ายๆ มีให้กรอก username และ password และปุ่ม login กับ cancel
ในการสมมติการทำงาน เราไม่ต้องกรอกอะไร ให้คลิกที่ปุ่ม login ก็จะไปเรียกคำสั่ง login ใน LoginComponent 
ให้ทำงาน ผลลัพธ์หน้าล็อกอินจะเป็นดังรูปด้านล่าง
 
 


 
 
เมื่อคลิกที่ปุ่ม Login ก็จะมีข้อความคำว่า Trying to log in ... ขึ้นอยู่ประมาณ 3 วินาที จากนั้นก็จะลิ้งค์ไปยังหน้า admin
 
ต่อไปเป็นส่วนของหน้า admin ที่เราจะมีการจำกัดสิทธิ์การเข้าใช้งาน โดยไฟล์ต่างๆ ที่เราได้มาจากการสร้างไว้แล้วในตอน
ต้นนั้น เราจะแก้ไขเพียง ไม่กี่ไฟล์เท่านั้น หลังๆ ก็จะประกอบด้วย admin-routing.module.ts , admin.component.html,
admin-center.component.html, admin-center.component.ts ส่วนไฟล์อื่นๆ ก็แทบจะไม่มีการเปลี่ยนแปลงใดๆ จะแสดง
เป็นข้อความ ค่าเริ่มต้นเช่น manage-users works! ตามแต่ละหน้า component 
 
ไฟล์ admin.module.ts ที่ได้จากการ generate จะได้ประมาณนี้
 
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { AdminRoutingModule } from './admin-routing.module';
import { AdminComponent } from './admin.component';
import { AdminCenterComponent } from './admin-center.component';
import { ManageUsersComponent } from './manage-users.component';
import { ManageProductsComponent } from './manage-products.component';

@NgModule({
  imports: [
    CommonModule,
    AdminRoutingModule
  ],
  declarations: [
    AdminComponent, 
    AdminCenterComponent, 
    ManageUsersComponent, 
    ManageProductsComponent
  ]
})
export class AdminModule { }
 
จะเห็นว่าในไฟล์ admin module เราจะไม่มีการเรียกใช้งาน providers แต่จะเรียกผ่า AdminRoutingModule แทน
 
ไฟล์ admin-routing.module.ts
 
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { AdminComponent } from './admin.component';
import { AdminCenterComponent } from './admin-center.component';
import { ManageUsersComponent } from './manage-users.component';
import { ManageProductsComponent } from './manage-products.component';

// import AuthGuardService ที่เราสร้างไว้เข้ามาใช้งาน
import { AuthGuardService } from '../auth-guard.service';

const adminRoutes: Routes = [
  {
    path:'admin',
    component:AdminComponent,
    // กำหนด guard service ให้กับ canActivate ที่ root ของ module ย่อย
    canActivate: [AuthGuardService], 
    children:[
      {
        path:'',
        component:AdminCenterComponent,
         // กำหนด guard service ให้กับ canActivateChild ให้กับ child ของ module ย่อย 
        canActivateChild: [AuthGuardService],
        children:[
          {
            path:'users',
            component:ManageUsersComponent
          },
          {
            path:'products',
            component:ManageProductsComponent
          }
        ]
      }
    ]
  }
];

@NgModule({
  imports: [RouterModule.forChild(adminRoutes)],
  exports: [RouterModule],
  providers:[
    AuthGuardService // ใช้งาน guard service ที่เราสร้างไว้
  ]
})
export class AdminRoutingModule { }
 
ในไฟล์ admin-routing.module.ts จะเห็นว่าทั้ง route path ของ root ใน module ย่อยมีการป้องกันการเข้าถึงด้วย
AuthGuardService โดยใน root จะเรียกใช้งานผ่าน canActivate นั้นหมายความว่า เราจะสามารถเข้ามายัง /admin
ได้ก็ต้องผ่านการตรวจสอบจาก AuthGuardService ก่อน โดยถ้าคืนค่ากลับมาเป็น true ก็จะสามารถเข้าใช้งานได้
ในขณะเดียวกัน AuthGuardService ยังทำการตรวจสอบการเข้าใช้งาน child ของ root ใน module ย่อยผ่าน 
canActivateChild ถ้าคืนค่าเป็น true ก็จะสามารถเข้าใช้งานใน /admin/products และ /admin/users ได้
 
ก่อนจะไปต่อที่ไฟล์ admin ในส่วนอื่นๆ เราย้อนกลับมาเพิ่มลิ้งค์หน้า admin ให้กับ root หลักของ App ที่ไฟล์
app.component.html ดังนี้ก่อน
 
ไฟล์ app.component.html
 
<nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="container">
      <div class="navbar-header">
        <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" 
              data-target="#navbar" aria-expanded="false" aria-controls="navbar">
          <span class="sr-only">Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" routerLink="/home" routerLinkActive="active">Home</a>
        <a class="navbar-brand" routerLink="/users" routerLinkActive="active">User</a>
        <a class="navbar-brand" routerLink="/products" routerLinkActive="active">Product</a>      
        <a class="navbar-brand" [routerLink]="[{ outlets: { popup: ['contact'] } }]" 
              routerLinkActive="active">Contact Us</a>   
        <a class="navbar-brand" routerLink="/admin" routerLinkActive="active">Admin</a>           
      </div> 
    </div>
  </nav>
  
  <div class="container">
    <br>
    <br>
    <h1>{{title}}</h1>
    <router-outlet></router-outlet>
    <router-outlet name="popup"></router-outlet>
  
  </div><!-- /.container -->
 
เราเพิ่มบรรทัดที่ 16 เข้ามา ผลลัพธ์จะแสดงเมนู Admin ตามรูปด้านล่าง
 
 


 
 
กลับมาที่ไฟล์ในส่วนของหน้า admin กันต่อ ส่วนต่อมาคือ ไฟล์ admin.component.html ซึ่งเป็นหน้าแสดง
ผลของ root ของ module ย่อยที่ชื่อ admin ให้เราปรับเป็นดังนี้
 
ไฟล์ admin.component.html
 
<p> admin works! </p>
<router-outlet></router-outlet>
 
โดยเพิ่ม router outlet เข้ามา ส่วนไฟล์ admin.component.ts เราไม่มีการทำงานใดๆ ในไฟล์นี้ จึงไม่มีการแก้ไข
ต่อไปให้ทำเช่นเดียวกันกับไฟล์ admin-center.component.html แต่เนื่องจากไฟล์นี้เราจะเป็นหน้าหลักของ admin
โดยจะมีการเพิ่มเมนูสำหรับเข้าถึง path ย่อยใน admin ด้วย ให้กำหนดไฟล์เป็นดังนี้
 
ไฟล์ admin-center.component.html
 
<p> admin-center works! </p>
<button [routerLink]="['/admin']" 
  routerLinkActive="btn-info" [routerLinkActiveOptions]="{ exact: true }" 
  class="btn btn-sm btn-default" >Home</button>
<button [routerLink]="['/admin/users']" 
  routerLinkActive="btn-info" 
  class="btn btn-sm btn-default" >Manage User</button>
<button [routerLink]="['/admin/products']" 
  routerLinkActive="btn-info" 
  class="btn btn-sm btn-default" >Manage Product</button>
<button class="btn btn-sm btn-danger" (click)="logout()" 
  type="button">Log Out</button>
<router-outlet></router-outlet>
 
โค้ดข้างต้นเราพยายามขึ้นบรรทัดใหม่เพื่อให้มองโค้ดง่ายขึ้น ข้างต้นเป็นการกำหนดการเชื่อมโยงลิ้งค์ทั่วไป
ผ่านการแสดงผลทาง router outlet สังเกตในบรรทัดที่ 3 มีส่วนใหม่ที่เพิ่มเข้ามาคือ การกำหนด 
 
 [routerLinkActiveOptions]="{ exact: true }" 
 
การกำหนดค่านี้ เพื่อระบุว่า ปุ่มนี้จะแสดง css class ชื่อ btn-info ที่ใช้เป็น active ก็ต่อเมื่อมี path เป็น /admin เท่านั้น
ซึ่งถ้าไม่กำหนดส่วนนี้ จะทำให้เวลาเราเข้าไปยัง /admin/products จะทำให้ปุ่มนี้ ยัง active ดังนั้น เพื่อไม่ให้ปุ่ม active
ถ้าอยู่ใน path ย่อยของ /admin ก็ให้ใส่ directive ข้างต้นเข้าไปด้วย
    สำหรับปุ่มสุดท้ายที่แสดงจะเป็นปุ่ม logout เพื่อยกเลิกหรือล้างค่าการล็อกอิน เมื่อกดล็อกเอา ก็จะลิ้งค์กลับไปที่หน้า
ล็อกอิน เพื่อขอสิทธิ์การเข้าใช้งานใหม่ก่อน
    ในไฟล์ admin-center.component.html นี้เรามีการใช้งาน router outlet ที่เป็น child ซ้อนเข้ามาอีก ดังนั้น เมื่อเราคลิก
ที่เมนู /admin/products หรือ /admin/users ข้อมูลของ path ทั้งสองก็จะมาแสดงใน outlet นี้
 
ต่อไฟล์เป็นส่วนของไฟล์ admin-center.component.ts อย่างที่กล่าวข้างต้นว่า เราจะมีการเรียกใช้คำสั่ง logout ดังนั้น
เราจึงต้องคำสั่งในส่วนนี้เพิ่มเข้ามา ดังนี้
 
ไฟล์ admin-center.component.ts
 
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute, ParamMap } from '@angular/router';

import { AuthService } from '../auth.service';

@Component({
  //selector: 'app-admin-center',
  templateUrl: './admin-center.component.html',
  styleUrls: ['./admin-center.component.css']
})
export class AdminCenterComponent implements OnInit {

  constructor(
    private authService:AuthService,
    private router:Router) { }

  // คำสั่ง สำหรับเรียกให้ AuthService ทำคำสั่งล็อกเอาท์อีกที
  logout() {
    this.authService.logout();
    this.router.navigate(['/login']); // หลังจากล็อกอาท์ให้ไปที่หน้าล็อกอิน
  }

  ngOnInit() {
  }

}
 
ตัวอย่างหน้า Admin ที่จะแสดงเมื่อทำการล็อกอินแล้ว จะได้ผลลัพธ์เป็นดังนี้
 
 


 
 
สามารถดูตัวอย่างผลลัพธ์ได้จาก demo ด้านล่าง เพิ่มเติม ตอนนี้ได้รู้จัก และทำความเข้าใจกับการใช้งาน guard ในส่วน
ของ canActivate และ canActivateChild ไปแล้ว เนื้อหาในตอนหน้า เราจะมาดูในส่วนที่เหลือกันต่อ รอติดตาม
 




กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ



อ่านต่อที่บทความ









เนื้อหาที่เกี่ยวข้อง









URL สำหรับอ้างอิง











เว็บไซต์ของเราให้บริการเนื้อหาบทความสำหรับนักพัฒนา โดยพึ่งพารายได้เล็กน้อยจากการแสดงโฆษณา โปรดสนับสนุนเว็บไซต์ของเราด้วยการปิดการใช้งานตัวปิดกั้นโฆษณา (Disable Ads Blocker) ขอบคุณครับ