1
1

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 3 years have passed since last update.

AngularのGuard使用時に、MatDialogでユーザに通知する

Last updated at Posted at 2019-12-27

#はじめに

権限を持ったユーザのみページアクセスの許可を出したいときに、AngularではGuardが提供されています。

AngularでGuardの導入

Guardはページ遷移の直前に動作し、アクセス権限を持ったユーザの判断をします。
ログイン認証などで使われますが、例えば会員と非会員ごとにアクセス可能なページを切り分けたい場合などにも使えます。

その際に、アクセスできなかったユーザに対して「なぜアクセスできないのか」を通知するのは重要だろうと考え、MatDialogと組み合わせて実装してみました。

#アプリケーションの構成

この記事ではGuardとDialogをどのように組み合わせたのかを紹介するために、認証済みでないユーザに対し、ログインが必要である旨を伝えます。

以下が構成です。

スクリーンショット 2019-12-27 16.53.35.png

このアプリケーションでは、AuthGardにSubjectを持たせて、ページ遷移に失敗した場合にnextでfalseを流します。

LoginComponent側ではsubscribeをしておき、Guadの結果を受け取ることでDialogを表示する、と言う流れにしています。

まずはGuadのコードです。

auth-guard.ts


@Injectable({
  providedIn: 'root'
})
export class InitializeGuard implements CanActivate {

  private authenticationSubject = new Subject<boolean>();

  constructor(
    private session$: SessionService,
    private router: Router,
  ) {}

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

      if () {
        // some code
      }

      // ページ遷移失敗時の結果を流す
      this.authenticationSubject.next(false);
      this.router.navigateByUrl('login');
  }

  get authentication$() {
    return this.authenticationSubject.asObservable();
  }
  
}

login-component.ts

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit, OnDestroy {

  onDestroy$ = new Subject<any>();

  constructor(
    private initialGuard: InitializeGuard,
    private dialog: MatDialog
  ) { }

  ngOnInit() {

    // guard の結果を購読
    this.initialGuard
      .authentication$
      .pipe(takeUntil(this.onDestroy$))
      .subscribe( result => {

        if (!result) {
          const dialog = this.dialog.open(AlertComponent, {
            data: {
              title: 'ログインしてください',
              button: '閉じる',
            }
          })
          
          // 購読の破棄
          dialog.afterClosed().subscribe( result => this.onDestroy$.next());
        } 
      })
  }

今回はダイアログの表示とGuardからの結果を受け取る箇所のみ記載しています。
FormGroupなどは割愛しています。

また、AlertDialogはComponent間で使い回しをしており、Component側からメッセージを入力させるように設計しているため、このような実装になっています。

ログイン画面はこのようにしています。

スクリーンショット 2019-12-27 17.10.29.png

未認証アクセスボタンはHomeComponentへのリンクを埋め込んでいます。
認証が住んでいない状態でクリックすると、このようなダイアログが表示されます。

スクリーンショット 2019-12-27 17.12.12.png

今回のようにGuardからの結果を各コンポーネントで購読するのは冗長なので、共通コンポーネントを挟んでおくと良さそうです。

#まとめ
これを使えば、非会員ユーザなどに対しての通知も簡単に実装できそうです。

私はこの方法しか思いつきませんでしたが、他にも思いついた方がいらっしゃればコメントをお願いいたします。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?