Angular でタブによるコンポーネントの切り替えを実装していきます。実はSSRの実装のときに使っているんですが、その時は本題でなかったというのもあり軽く流していました。今回は解説つきです。
完成しているコードは下記にあります。
環境
- 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.isActive
が true
)のとき、そのタブが強調して表示されます。
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/」にアクセスすると確認できます。

コメント