【Angular】Angular Materialでのタブの実装

 Angular でタブによるコンポーネントの切り替えを実装していきます。実はSSRの実装のときに使っているんですが、その時は本題でなかったというのもあり軽く流していました。今回は解説つきです。

 完成しているコードは下記にあります。

Angular-sample/tabs at main · tsuneken5/Angular-sample
Contribute to tsuneken5/Angular-sample development by creating an account on GitHub.

環境

  • node: 18.20.0
  • Angular CLI:17.0.0
  • Angular Material:17.3.10

 今回からAngularのバージョンを17にしました。

プロジェクトの作成

$ ng new tabs

Angular Materialのインストール

$ ng add @angular/material

コンポーネントの生成

$ ng generate component page-a
$ ng generate component page-b

 タブの切替時の確認用のコンポーネントです。コードの変更はしません。

ルーティング

import { Routes } from '@angular/router';

import { PageAComponent } from './page-a/page-a.component'; // 追加
import { PageBComponent } from './page-b/page-b.component'; // 追加

export const routes: Routes = [ // 変更
  { path: '', redirectTo: '/page-a', pathMatch: 'full' },

  { path: 'page-a', component: PageAComponent },
  { path: 'page-b', component: PageBComponent },

  { path: '**', redirectTo: '/page-a' }
];

タブの実装

<nav mat-tab-nav-bar [tabPanel]="tabPanel">
  <a mat-tab-link *ngFor="let routeLink of routeLinks" [routerLink]="routeLink.path" routerLinkActive
    #rla="routerLinkActive" [active]="rla.isActive">
    {{ routeLink.label }}
  </a>
</nav>

<mat-tab-nav-panel #tabPanel>
  <router-outlet></router-outlet>
</mat-tab-nav-panel>
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet, RouterModule } from '@angular/router'; // RouterModuleを追加
import { MatTabsModule } from '@angular/material/tabs';       // 追加

@Component({
  selector: 'app-root',
  standalone: true,
  imports:
    [
      CommonModule,
      RouterOutlet,
      RouterModule,           // 追加
      MatTabsModule,          // 追加
    ],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'tabs';

  public routeLinks = [
    { label: 'page-a', path: '/page-a' },
    { label: 'page-b', path: '/page-b' },
  ];
}

app.component.html

1行目

 mat-tab-nav-bar はタブのような外観と動作を実装するためのディレクティブです。 [tabPanel]="tabPanel" でタブパネルへの参照を設定しています。

2~5行目

 *ngFor ディレクティブを使用して、routeLinks 配列の各要素に対してリンクを生成しています。

 routerLinkActive ディレクティブを使用して、現在アクティブなリンクを追跡しています。#rla はテンプレート参照変数で、この変数を通じてアクティブ状態にアクセスできるようになります。

 [active]="rla.isActive" でタブのアクティブ状態を rla.isActive に基づいて設定します。タブがアクティブ ( rla.isActivetrue )のとき、そのタブが強調して表示されます。

8~10行目

 現在のルートに対応するコンポーネントをここに表示します。 #tabPanel で参照変数を宣言して、mat-tab-nav-bar と関連付けをしています。

 この程度のソースであれば <mat-tab-nav-panel> がない下記のソースでも動作しますが、 <mat-tab-nav-panel> がないと予期しない不具合が起きる可能性があるみたいです。

<nav mat-tab-nav-bar>
  <a mat-tab-link *ngFor="let routeLink of routeLinks" routerLink="{{ routeLink.path }}" routerLinkActive
    #rla="routerLinkActive" [active]="rla.isActive">
    {{ routeLink.label }}
  </a>
</nav>

<router-outlet></router-outlet>

app.component.ts

 TypeScript では HTML で呼び出す配列を宣言しているだけです。

確認

$ ng serve

 ブラウザから「http://localhost:4200/」にアクセスすると確認できます。

コメント

タイトルとURLをコピーしました