17
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Systemi(システムアイ)Advent Calendar 2022

Day 5

Angularで知っておきたい3つの機能

Last updated at Posted at 2022-12-04

はじめに

本稿はシステムアイ Advent Calendar 2022の記事となります。

Angular(アンギュラー)はGoogle社によって開発されているTypeScriptベースのフロントエンドフレームワークです。React、Vue.jsと並んで人気があるフレークワークの一つとなっています。(厳密にはReact、Vue.jsはフレームワークではなくライブラリです)

また、Angularの特徴としてフルスタック(全部入り)のフレームワークとなり、標準の機能だけでアプリケーションが作ることができます。

今回はそんなAngularの知っておきたい基本の3つの機能をお送りします。

Service

Angularのサービス(Service)という機能があります。サービスを使うとコンポーネントからロジック部分を分離する(別ファイルに分ける)ことができます。
例えば、サーバーからのデータ取得、入力チェック、ログ出力などをサービスに記述することで、コンポーネントから左記ロジックを切り離せるため、サービス、コンポーネントの再利用性があがります。

また、サービスをシングルトン(単一インスタンス)にし、アプリケーションにひとつだけ存在させることができます。サービスを定義するInjectableデコレータにprovidedIn: 'root'を書くだけでシングルトンにでき、アプリケーション内で利用することができます。(※)

Angular CLIが導入されている環境であれば、下記コマンドを実行するだけで簡単にシングルトンのサービスが作成できます。

ng generate service user
src/app/user.service.ts
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class UserService {
}

※Angularが6.0未満の場合は、providedIn: 'root'ではなく、AppModuleにサービスを定義する必要があります。

src/app/app.module.ts
@NgModule({
  ...
  providers: [UserService],
  ...
})

HttpInterceptor

HTTPリクエスト/レスポンスに共通の前処理を挟み込むことができます。
例えばリクエストヘッダーに認証トークンを設定したり、レスポンスの結果を共通的に扱いたい場合に本機能を利用します。

src/app/token.interceptor.ts
import { Injectable } from '@angular/core';
import {
  HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse
} from '@angular/common/http';

import { Observable,tap } from 'rxjs';

@Injectable()
export class TokenInterceptor implements HttpInterceptor {

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // sesion storageに保存されているトークンを取り出す
    const token = sessionStorage.getItem('token');

    // 全てのリクエストのAuthorizationヘッダーにトークンをセット
    const newRequest = request.clone({
        headers: request.headers.set(
            'Authorization', `Bearer ${token}`
        )
    });
    return next.handle(newRequest);
  }
}

レスポンスヘッダーからトークンを取り出す場合はreturn next.handle(newRequest);を下記のように書き換えます。

src/app/token.interceptor.ts
...
    return next.handle(newRequest).pipe(
      tap((res) =>{
        if(res instanceof HttpResponse){
          const token = res.headers.get('token')
          if(token){
            sessionStorage.setItem('token',token)
          }
        }
      })
    );
...

Guard

Angularのガード(Guard)を使えば、ルーティング前後に処理を挟むことができます。
例えば、次のページへ遷移する際に権限のチェックをする際などにシーンに利用します。

こちらもAngular CLIが導入されている環境であれば、下記コマンドを実行するだけで簡単にガードを作成できます。

ng generate guard auth
? Which interfaces would you like to implement? CanActivate
CREATE src/app/auth.guard.spec.ts (331 bytes)
CREATE src/app/auth.guard.ts (457 bytes)
PS C:\Users\systemi\work\angular\my-app> 
src/app/auth.guard.ts
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    return true;
  }
  
}

canActivateのリターンがtrueの場合は通常通りページに遷移、falseの場合は遷移不可にできます。
下記はガードを書き換え、session storageにトークンがない場合はログインページに転送するようにしています。

src/app/auth.guard.ts
...
  constructor(
    private router: Router
  ) {}

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

      if (!sessionStorage.getItem('token')) {
        this.router.navigate(['login']);
        return false;
      }
      return true;
  }

ガードしたいルートに対してガードを記述します。

src/app/app-routing.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes } from '@angular/router';
import { LoginComponent } from './login/login.component'
import { AuthGuard } from './auth.guard';

const routes: Routes = [
  { path: 'login', component: LoginComponent , canActivate: [AuthGuard] }
];

@NgModule({
  imports: [CommonModule,RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule { }

まとめ

Angularで知っておきたい3つの機能をご紹介しました。
そのほかにもディレクティブ、パイプ、バリデーション、遅延ロードなどたくさんの機能を標準で備えたAngularにぜひ触れてみてください。

Angular
https://angular.jp/

17
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?