Chuyển đến nội dung chính

Ôn tập Angular: Guards và Resolver

Guard là gì

Trong Angular, Guard là một trong những công cụ mạnh mẽ dùng để bảo vệ các route trong ứng dụng. Guard giúp kiểm soát quyền truy cập của người dùng vào các route cụ thể dựa trên các điều kiện như quyền hạn (authorization), quyền đăng nhập (authentication), hoặc bất kỳ logic nào mà bạn muốn áp dụng trước khi cho phép người dùng điều hướng tới một trang nào đó.
Guard trong Angular hoạt động giống như các interceptor, nhưng nó chủ yếu kiểm tra trước khi cho phép truy cập một route. Nó giúp đảm bảo rằng người dùng không thể truy cập vào các phần không được phép của ứng dụng.

Có 4 loại guard:

  • canMatch: dùng để verify 1 Route có thể được load. Bạn có thể định nghĩa nhiều Routes cho 1 single path và dùng Guard để chọn 1 dựa trên điều kiện có sẵn.
  • canActivate: kiểm soát quyền truy cập vào một Route. Ví dụ, chỉ những người dùng đã đăng nhập mới được phép truy cập vào một số trang cụ thể.
  • canActivateChild: canActivateChild tương tự như canActivate, nhưng nó được áp dụng cho các Route con. Guard này sẽ được kích hoạt khi điều hướng đến một Route con.
  • canDeactivate: canDeactivate giúp kiểm soát việc rời khỏi một trang. Ví dụ, nếu người dùng có các thay đổi chưa được lưu trên một form, guard này có thể yêu cầu xác nhận trước khi người dùng rời khỏi trang.

Cấu trúc thư mục

Angular's route guards là các interface có thể cho bộ định tuyến biết liệu nó có cho phép điều hướng đến một route được yêu cầu hay không. Nó đưa ra quyết định này bằng cách tìm kiếm một giá trị trả về true hoặc false từ một lớp được implement từ guard interface.

📁 app
    └──📂 components
        ├──login.component.ts
        ├──register.component.ts
        ├──....ts
    └──📂 guards //(e.g., AuthGuard, LoginGuard, DeactivateGuard)
    └──📂 services
    └──📂 pages

Tạo Angular guard từ command
ng generate guard guard-name

Khi chạy lệnh, bạn cũng sẽ được hỏi chọn kiểu guard bạn muốn tạo (ví dụ CanActivate, CanDeactivate, CanActivateChild...), dựa trên nhu cầu của dự án.

Ví dụ:
ng generate guard login
Angular CLI sẽ tạo ra 2 file login.guard.ts và login.guard.spec.ts
import { CanMatchFn } from '@angular/router';

export const loginGuard: CanMatchFn = (route, segments) => {
  return true;
};
Giả sử bạn muốn kiểm tra login
import { CanMatchFn } from '@angular/router';

export const loginGuard: CanMatchFn = (route, segments) => {
  const isLoggedIn = localStorage.getItem('isLoggedIn');

  if (isLoggedIn === 'true') {
    return false;
  }

  return true;
};

Angular Resolver là gì?

Angular Resolver cho phép tải trước data cho một route trước khi chuyển đến route đó. Nó thực chất là 1 đoạn code xen giữa việc user click vào url và việc load component tương ứng.

Form Login

Chúng ta sẽ sử dụng các thành phần như FormControl, FormGroup, ReactiveFormsModule, và Validators để tạo và quản lý form đăng nhập một cách dễ dàng.

FormControl là gì?

FormControl đại diện cho một phần tử form đơn lẻ, ví dụ: một trường input trong form. Nó chứa giá trị và trạng thái của trường đó (ví dụ: hợp lệ hay không hợp lệ). Mỗi trường dữ liệu trong form được kiểm soát bởi một đối tượng FormControl.

FormGroup là gì?

FormGroup là một tập hợp các FormControl giúp quản lý nhiều trường input trong cùng một form. Nó đại diện cho toàn bộ form và giúp xử lý form dưới dạng nhóm thay vì từng trường riêng lẻ.
ReactiveFormsModule là gì?

ReactiveFormsModule là module của Angular giúp bạn sử dụng các tính năng của Reactive Forms. Bạn cần import ReactiveFormsModule vào ứng dụng để làm việc với FormControl, FormGroup, và các validator trong form.

Validators là gì?

Validators là các hàm kiểm tra xem dữ liệu nhập vào có hợp lệ không. Angular cung cấp một số validator tích hợp sẵn như:

  • Validators.required: Yêu cầu trường phải được nhập.
  • Validators.minLength: Kiểm tra xem độ dài của chuỗi nhập vào có đủ không.
  • Validators.email: Kiểm tra xem chuỗi nhập vào có phải email hợp lệ không.

Các bước xây dựng trang đăng nhập bằng Reactive Forms

Cài đặt ReactiveFormsModule

import { Component } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { NgIf } from '@angular/common';

@Component({
  selector: 'app-login',
  standalone: true,
  imports: [ReactiveFormsModule, NgIf],
  templateUrl: './login.component.html',
  styleUrl: './login.component.scss'
})
export class LoginComponent {
  loginForm: FormGroup;

  constructor(private formBuilder: FormBuilder) {
    this.loginForm = this.formBuilder.group({
      email: ['', [Validators.required, Validators.email]],
      password: ['', [Validators.required, Validators.minLength(6)]],
    });
  }

  onSubmit() {
    if (this.loginForm.valid) {
      console.log('Form Submitted', this.loginForm.value);
    } else {
      console.log('Form is invalid');
    }
  }
}
Cập nhât lại template
<div class="login-card">
    <div class="card-title">
        <h1>Login</h1>
        <span>You don't have an account? <a routerLink="/signup">Sign up</a></span>
    </div>
    <form class="form-group" [formGroup]="loginForm" (ngSubmit)="onSubmit()">
        <input name="email" type="email" formControlName="email" placeholder="Email" class="form-control" />
        <div *ngIf="loginForm.get('email')?.invalid && loginForm.get('email')?.touched">
            <div *ngIf="loginForm.get('email')?.errors?.['required']">
              Email is required
            </div>
            <div *ngIf="loginForm.get('email')?.errors?.['email']">
              Please enter a valid email address
            </div>
          </div>
        <input type="password" formControlName="password" placeholder="Password" class="form-control" />
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>

</div>
Update file css
* {
    box-sizing: border-box;
}

:host {
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

.login-card {
    display: flex;
    flex-direction: column;
    margin: 10px 10px;
    box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.3);
    background-color: #ffffff;
    padding: 10px;
    border-radius: 10px;
    width: 40%;

}

.login-card input {
    margin: 5px 0;
    width: 100%;
    background-color: #e2e2e2;
    border: none;
    outline: none;
    padding: 12px 20px;
    border-radius: 4px;
}

.login-card button {
    background-color: #4796ff;
    color: #ffffff;
    font-size: 16px;
    outline: none;
    border-radius: 5px;
    border: none;
    padding: 8px 15px;
    width: 100%;
}


.card-title h1 {
    font-size: 26px;
    font-weight: bold;
}
Thêm loginComponent vào file app.routes.js
import { Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { AngularComponent } from './angular/angular.component';
import { ReactComponent } from './react/react.component';
import { AboutComponent } from './about/about.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
import { LoginComponent } from './pages/login/login.component';

export const routes: Routes = [
    {path: '', component: HomeComponent},
    {
        path: 'login',
        component: LoginComponent,
        //canMatch: [LoginGuard],
    },
    {path: 'angular/:category', component: AngularComponent},
    {path: 'react', component: ReactComponent},
    {path: 'about', component: AboutComponent},
    { path: '**', component: PageNotFoundComponent },
];


Nhận xét

Bài đăng phổ biến từ blog này

[ASP.NET MVC] Authentication và Authorize

Một trong những vấn đề bảo mật cơ bản nhất là đảm bảo những người dùng hợp lệ truy cập vào hệ thống. ASP.NET đưa ra 2 khái niệm: Authentication và Authorize Authentication xác nhận bạn là ai. Ví dụ: Bạn có thể đăng nhập vào hệ thống bằng username và password hoặc bằng ssh. Authorization xác nhận những gì bạn có thể làm. Ví dụ: Bạn được phép truy cập vào website, đăng thông tin lên diễn đàn nhưng bạn không được phép truy cập vào trang mod và admin.

ASP.NET MVC: Cơ bản về Validation

Validation (chứng thực) là một tính năng quan trọng trong ASP.NET MVC và được phát triển trong một thời gian dài. Validation vắng mặt trong phiên bản đầu tiên của asp.net mvc và thật khó để tích hợp 1 framework validation của một bên thứ 3 vì không có khả năng mở rộng. ASP.NET MVC2 đã hỗ trợ framework validation do Microsoft phát triển, tên là Data Annotations. Và trong phiên bản 3, framework validation đã hỗ trợ tốt hơn việc xác thực phía máy khách, và đây là một xu hướng của việc phát triển ứng dụng web ngày nay.

Tổng hợp một số kiến thức lập trình về Amibroker

Giới thiệu về Amibroker Amibroker theo developer Tomasz Janeczko được xây dựng dựa trên ngôn ngữ C. Vì vậy bộ code Amibroker Formula Language sử dụng có syntax khá tương đồng với C, ví dụ như câu lệnh #include để import hay cách gói các object, hàm trong các block {} và kết thúc câu lệnh bằng dấu “;”. AFL trong Amibroker là ngôn ngữ xử lý mảng (an array processing language). Nó hoạt động dựa trên các mảng (các dòng/vector) số liệu, khá giống với cách hoạt động của spreadsheet trên excel.