【Angular】Angular Materialの使用方法 - ChuN6868/CodeChrysalis-fullstuck-project GitHub Wiki

環境構築

下記のコマンドでインストールする

npm install @angular/[email protected] @angular/[email protected]
// angular/materialとcdkのバージョンはマイナーバージョンを含めて揃える必要がある
// angular/materialとcdkのメジャーバージョンはangularのメジャーバージョンと揃える必要がある(今回の場合はv18)
// 最終的にpackage.jsonやnode_modulesにmaterialの記載があり、angular.jsonにテーマが記載されていれば運用できる

angular.jsonを下記のように修正

// build.options.stylesの箇所を下記のように修正
// 特に必要はないが、test.options.stylesにも同様の記載をしておくのが良いかも
"styles": [
  "src/styles.css",
  "node_modules/@angular/material/prebuilt-themes/indigo-pink.css" // ←これ
],

各機能の使い方

ボタン系

最低限、component.tsに下記の記載が必要。

import { MatButtonModule } from '@angular/material/button';

@Component({
  imports: [
    MatButtonModule,
  ],
})

その後、component.htmlに下記のように記載

// colorは種類が少ないので、代わりにclassで自分で定義も可
// disabledを追記することで非活性にできる
<button mat-raised-button color="primary">決定ボタン</button>

※colorにprimaryを設定しても色が変わらない場合はangular.jsonの下記を確認

// build.options.stylesの箇所が下記のようになっていることを確認
// 特に必要はないが、test.options.stylesにも同様の記載をしておくのが良いかも
"styles": [
  "src/styles.css",
  "node_modules/@angular/material/prebuilt-themes/indigo-pink.css" // ←たいていの場合、この記載が不足している
],

※cssで作成したclassを追記しても色の変更がされない場合は下記のようにcssを書く

// (非推奨)
// !importantを追記することでAngular Materialの設定を上書きできるようになる
// ただし、buttonにdisabledを設定してもここで設定した色から変わらなくなってしまう
.success-button {
  background-color: #4caf50 !important;
  color: white !important;
}

.success-button:hover {
  background-color: #43a047 !important;
}
// (推奨)
// F12で優先されているstyleを確認したところ、--mdc-protected-button-container-colorの変数を上書きする必要があることが分かった
// disabledを設定すれば色もdisabledが反映される
.success-button {
  --mdc-protected-button-container-color: #4caf50;
  --mdc-protected-button-label-text-color: white;
}

.success-button:hover {
  --mdc-protected-button-container-color: #43a047;
}

テーブル系

最低限、component.tsに下記の記載が必要。

import { MatTableModule } from '@angular/material/table';

@Component({
  imports: [
    MatTableModule,
  ],
})
export class SampleComponent {
  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource = [
    { position: '1', name: '水素', weight: 1.0079, symbol: 'H' },
    { position: '2', name: 'ヘリウム', weight: 4.0026, symbol: 'He' },
  ];
}
// 値を入れたくないセルがあれば、name: '水素'の箇所を削除すれば消えてくれる

その後、component.htmlに下記のように記載
※class="mat-elevation-z8"はドロップシャドウの強さであり、z0は影なしで、z24が最大の強さとなる(classをそもそも記述しなければ影なしとなるが明示的に書く場合はz0を記述する)

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
  <!-- Position Column -->
  <ng-container matColumnDef="position">
    <th mat-header-cell *matHeaderCellDef>ポジション</th>
    <td mat-cell *matCellDef="let element">{{ element.position }}</td>
  </ng-container>

// ボタンをテーブル内に配置したい場合は、下記の要に記載
  <!-- Name Column -->
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef></th>
    <td mat-cell *matCellDef="let element">
      <button mat-raised-button class="success-button">登録</button>
    </td>
  </ng-container>

  <!-- Weight Column -->
  <ng-container matColumnDef="weight">
    <th mat-header-cell *matHeaderCellDef></th>
    <td mat-cell *matCellDef="let element">{{ element.weight }}</td>
  </ng-container>

  <!-- Symbol Column -->
  <ng-container matColumnDef="symbol">
    <th mat-header-cell *matHeaderCellDef>記号</th>
    <td mat-cell *matCellDef="let element">{{ element.symbol }}</td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>

アコーディオン系

下記の公式ページが参考になるかも
https://v18.material.angular.dev/components/expansion/overview

最低限、component.tsに下記の記載が必要。

import {MatExpansionModule} from '@angular/material/expansion';

@Component({
  imports: [
    MatExpansionModule
  ],
})

その後、component.htmlに下記のように記載

<mat-expansion-panel hideToggle>
    <mat-expansion-panel-header>
        <mat-panel-title> This is the expansion title </mat-panel-title>
        <mat-panel-description> This is a summary of the content </mat-panel-description>
    </mat-expansion-panel-header>
    <p>This is the primary content of the panel.</p>
</mat-expansion-panel>

※hideToggleを記述すると「展開・折りたたみ用のアイコンを隠す」という意味になるので基本的には不要 ※BrowserAnimationsModuleが読み込まれていない場合はエラーが発生するので、provideAnimationsを使ってアニメーションを有効化する必要がある
※main.tsでapp.config.tsをimportしている場合は下記のようにapp.config.tsを修正する

import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideAnimations } from '@angular/platform-browser/animations'; // ← 追加

import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes),
    provideAnimations() // ← 追加
  ]
};

複数のアコーディオンを設定したい場合

mat-accordionで複数のaccordionを囲むと管理しやすい

// multiを定義すると複数同時に展開でき、記述しないとどれか一つしか同時に展開できなくなる
<mat-accordion multi>
    <mat-expansion-panel>
        <mat-expansion-panel-header>
            <mat-panel-title> This is the expansion title </mat-panel-title>
            <mat-panel-description>
            </mat-panel-description>
        </mat-expansion-panel-header>
    </mat-expansion-panel>

    <mat-expansion-panel>
        <mat-expansion-panel-header>
            <mat-panel-title>Another Title</mat-panel-title>
        </mat-expansion-panel-header>
        <p>Other Content</p>
    </mat-expansion-panel>
</mat-accordion>

アイコン系

index.htmlに下記を追加

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

component.tsに下記を追加

import { ChangeDetectionStrategy, Component } from '@angular/core';
import {MatIconModule} from '@angular/material/icon';

@Component({
  imports: [
    MatIconModule
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
})

component.htmlに下記を記述

// Homeのアイコン
<mat-icon aria-hidden="false" aria-label="Example home icon" fontIcon="home"></mat-icon>

// チェックサークルのアイコン
<mat-icon>check_circle_outline</mat-icon>

アイコンリストは下記のリンク先などを参照
https://www.angularjswiki.com/angular/angular-material-icons-list-mat-icon-list/

アコーディオン×アイコン(自分で細かく設定したい場合)

アコーディオンのタイトルに「展開・折り畳み」のアイコンを追加し、アイコンの回転をできるようにする
※hideToggleを削除すればAngularが用意しているものを使えるので、あくまで自分で設定したい場合の話
component.htmlのを修正

<mat-expansion-panel hideToggle #panel> // #panelを追加
    <mat-expansion-panel-header>
        <mat-panel-title> This is the expansion title </mat-panel-title>
        <!-- ↓アコーディオンの補足情報を書ける場所だが、今回はここにアイコンを配置 -->
        <mat-panel-description>
            <mat-icon [class.rotated]="panel.expanded">expand_more</mat-icon> // 追加
        </mat-panel-description>
    </mat-expansion-panel-header>
</mat-expansion-panel>

style.cssに追記

mat-icon {
  transition: transform 0.3s ease;
}

mat-icon.rotated {
  transform: rotate(180deg); /* expand_more → expand_less に見える */
}

// transition | CSSのプロパティにアニメーション的な変化を加える設定
// transform | transformプロパティ(回転・拡大縮小など)の変化にアニメをつける
// 0.3s | 変化にかける時間:0.3秒でアニメーションが完了する
// ease | アニメーションの速度カーブ(最初と最後がなめらか、中間が速め)

panel.expandedとrotatedクラスの関係性

[class.rotated]="panel.expanded"
→ これは「panel.expanded が true のとき、rotated クラスを付ける」というAngularの構文です。

panel.expanded
→ これは <mat-expansion-panel> が現在展開されているかどうかを示す 内部の状態プロパティです(Angular Materialが提供)

## 処理の流れ
初期状態(折りたたまれている) → panel.expanded === false

クラス rotated は付かない

transform: none → ▼ 表示

アコーディオンをクリックして展開
→ panel.expanded === true

rotated クラスが付く

transform: rotate(180deg) が有効 → ▼ がくるっと回転して ▲ 風になる

テキストボックスの使い方

参考:https://v18.material.angular.dev/components/form-field/overview
component.tsに下記を追加

import {MatFormFieldModule} from '@angular/material/form-field';
import {MatInputModule} from '@angular/material/input';

@Component({
  imports: [
    MatFormFieldModule,
    MatInputModule,
  ],
})

component.htmlに下記を追加

// appearanceをfillにすると下線だけ、outlineにすると枠線ができる(デフォルトはfill)
<mat-form-field appearance="fill">
  <mat-label>Textarea</mat-label>
  <textarea matInput></textarea>
</mat-form-field>
⚠️ **GitHub.com Fallback** ⚠️