🐟

【Angular Material】タブの数を可変にして、選択中のタブにスタイルを付与したい!

2021/05/08に公開2

はじめに

Angular MaterialのTabsで選択したタブのタイトルにのみ変更を加えたり、スタイルを付与したりする実装をしたので、記事にしてみました!
同じような実装をしている方の助けになればと思います。

※完成形stackblitzを貼っておきます!
https://stackblitz.com/edit/angular-mmsxvm?file=src%2Fapp%2Ftab-group-dynamic-height-example.ts

やりたいこと

・Angular MaterialのTabsを使ってタブの切り替えを実装したい。
・選択されているタブのタイトルを変更したい。
・選択されているタブのスタイル変更したい。

APIのレスポンスに応じて、タブの数を可変にしたかったので、Viewは以下のような実装にしています。

tab-group-dynamic-height-example.html
<mat-tab-group>
  <div *ngFor="let hoge of array; let i = index">
    <mat-tab>
      <!-- タブのタイトル -->
      <ng-template mat-tab-label>
        <p>{{ hoge }}</p>
      </ng-template>
      <!-- タブの中身 -->
      <p>{{ "Content" + i }}</p>
    </mat-tab>
  </div>
</mat-tab-group>

コンポーネントでViewに渡す配列を定義します。

tab-group-dynamic-height-example.ts
import { Component } from "@angular/core";

@Component({
  selector: "tab-group-dynamic-height-example",
  templateUrl: "tab-group-dynamic-height-example.html",
  styleUrls: ["tab-group-dynamic-height-example.css"]
})

export class TabGroupDynamicHeightExample {
  public array = ["a", "b", "c"];
}

これで以下のように配列内の文字列が順番にタブのタイトルとして表示され、コンテンツとして "Content" + インデックス番号が表示されます。
スクリーンショット 2021-04-29 18.23.15.png

これを以下の画像のように選択されているタブのみ、タイトルを大文字にして、背景に色をつけて、横幅を広げるような実装をやっていきます。
スクリーンショット 2021-04-29 18.42.47.png

実装

実装する内容は主に以下の3点になります。
・選択されているタブを判断する。
・選択されているタブのタイトルを大文字にする。
・選択されているタブのみスタイルを付与する。


○選択されているタブを判断する。

View側
selectedTabChangeでタブの選択が変更されたときに発行されるイベントを拾って、tabClickメソッドに渡します。

tab-group-dynamic-height-example.html
<mat-tab-group (selectedTabChange)="tabClick($event)">
・・・
</mat-tab-group>

Component側
拾ったeventに選択されているインデックス番号のデータが存在する為、そのデータをselectedTabに代入します。
これによりView側で選択されているタブを判断できます。

tab-group-dynamic-height-example.ts

export class TabGroupDynamicHeightExample {

  public array = ["a", "b", "c"];

  public selectedTab = 0;

  public tabClick(event: any) {
    this.selectedTab = event.index;
  }
}


○選択されているタブのタイトルを大文字にする。
View側
以下のようにselectedTabをフラグとして、選択されている場合とされていない場合で、Viewを切り替えます。

tab-group-dynamic-height-example.html
<mat-tab-group (selectedTabChange)="tabClick($event)">
  <div *ngFor="let hoge of array; let i = index">
    <mat-tab>
      <ng-template mat-tab-label *ngIf="selectedTab !== i">
        <p>{{ hoge }}</p>
      </ng-template>
      <ng-template mat-tab-label *ngIf="selectedTab === i">
        <p>{{ hoge.toUpperCase() }}</p>
      </ng-template>
      <p>{{ "Content" + i }}</p>
    </mat-tab>
  </div>
</mat-tab-group>


○選択されているタブのみスタイルを付与する。
どうやって、CSSに「選択されているタブ」という情報を渡そうかなあと少し悩みました。。
要素を検証ツールで確認していたところ・・・
下記のように選択されているタブのタイトル要素のみに 「mat-tab-labe-active」というクラスが付与されている事を見つけました!
スクリーンショット 2021-04-29 19.05.52.png

mat-tab-label-activeクラスにスタイルを付与します。

tab-group-dynamic-height-example.css
/* ここで詳しくは説明しませんが、::ng-deepを使用しないとスタイルは反映されません! */
::ng-deep .mat-tab-label-active {
  background-color: red;
  width: 100%;
}

これで実装できるはず!!

まとめ

Angular Material等を使用する際は、検証ツールで自動的に付与されているクラス等を確認する事で、色々とカスタマイズできる事を学べました!
何か意見等があれば是非ともコメント頂ければ嬉しいです。

Discussion

teatwoteatwo

<div *ngFor="let hoge of array; let i = index">のところは<ng-container>にすれば余計なdivタグが出力されなくなってもっと良さそうに思いました!もし、スタイルなどで使っているのでしたら無視してください。

sea_takusea_taku

コメントありがとうございます!

ご指摘頂いた通りですね!たしかに無駄なdivタグでした。。
ありがとうございます!