Angular Materialテーマの動的変更

2020年8月3日月曜日

Angular

t f B! P L
Angular Materialの公式のサイトは、メニューからテーマ(画面の色)を動的に変更できるようになっています。公式サイトのソースコードを参考に、簡単なAngularプロジェクトでテーマの動的変更を試行しました。

簡単なAngular Materialプロジェクトの作成

まず、新しくAngularのプロジェクトを作成します。Angularのバージョンは10.0.7です。スタイルシートのフォーマットはSCSSにしました。

$ng new theme-test
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? SCSS 
このプロジェクトでAngular Materialを利用できるようにします。Angular Materialのバージョンは10.1.1です。

$cd theme-test
$ng add @angular/material
テスト用として、MatToolBarを使えるようにします。そのための変更は、src/app/app.module.tsに対して行います。

import {MatToolbarModule} from '@angular/material/toolbar'; 
…
@NgModule ({....
  imports: [...,
    MatToolbarModule,
…]
})
トップ画面にMatToolBarを表示します。そのための変更は、src/app/app.module.htmlに対して行います。

…
<h2>Resources</h2>
  <p>Here are some links to help you get started:</p>
  <mat-toolbar color="primary">Angular Material ToolBar</mat-toolbar>@NgModule ({....
…
ng serveを実行してlocalhost:4200にアクセスすると、次のような画面が表示されます。

Angular Materialソースコードのクローン

参考にするAngular Materialのソースコードをgithubからcloneします。

$git clone https://github.com/angular/material.angular.io

テーマの動的変更

Angular Materialのソースコードから、テーマの動的変更に最低限必要なファイルをプロジェクトにコピーします。 また、最低限必要なコード変更をプロジェクトに加えます。

ファイルのコピー

以下のファイルをAngular Materialのソースコード(~/material.angular.io)から、プロジェクト(~/theme-test)にコピーします。

mkdir ~/theme-test/src/app/shared
cp -r ~/material.angular.io/src/app/shared/navbar ~/theme-test/src/app/shared/
cp -r ~/material.angular.io/src/app/shared/theme-picker/ ~/theme-test/src/app/shared/
cp -r ~/material.angular.io/src/app/shared/style-manager/ ~/theme-test/src/app/shared/
cp -r ~/material.angular.io/src/highlightjs/ ~/theme-test/src/
cp -r ~/material.angular.io/src/styles ~/theme-test/src/
cp ~/material.angular.io/src/_app-theme.scss ~/theme-test/src/

angular.jsonの編集

angular.jsonを編集して、スタイルシートをassetsディレクトリから参照できるようにします。また、extractCssオプションにtrueを設定します。

     "architect": {
        "build": {
          "options": {
            "extractCss": true,
            "styles": [
              "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
              "src/styles.scss",
              {
                "input": "src/highlightjs/material-light.scss"
              },
              {
                "lazy": true,
                "inject": false,
                "input": "src/styles/custom-themes/pink-bluegrey.scss",
                "bundleName": "assets/pink-bluegrey"
              },
              {
                "lazy": true,
                "inject": false,
                "input": "src/styles/custom-themes/deeppurple-amber.scss",
                "bundleName": "assets/deeppurple-amber"
              },
              {
                "lazy": true,
                "inject": false,
                "input": "src/styles/custom-themes/indigo-pink.scss",
                "bundleName": "assets/indigo-pink"
              },
              {
                "lazy": true,
                "inject": false,
                "input": "src/styles/custom-themes/purple-green.scss",
                "bundleName": "assets/purple-green"
              }
            ],
extractCssオプションにtrueを設定しないと、次のようなエラーが発生します。

The resource from “http://localhost:4200/assets/pink-bluegrey.css”
was blocked due to MIME type (“text/html”) mismatch (X-Content-Type-Options: nosniff).

ThemePickerModuleの追加

プロジェクトのsrc/app/app.module.tsを編集して、ThemePickerModuleを追加します。 また、HttpClientModuleを追加します。

import {MatToolbarModule} from '@angular/material/toolbar'; 
import { ThemePickerModule } from './shared/theme-picker';
import {HttpClientModule} from '@angular/common/http'; 

…
@NgModule ({....
  imports: [...,
    MatToolbarModule,
    ThemePickerModule,
    HttpClientModule,
…]
})
HttpClientModuleを追加しないと、次のようなエラーが発生します。

ERROR Error: "Could not find HttpClient provider for use with
Angular Material icons. Please include the HttpClientModule 
from @angular/common/http in your app imports."

テーマ選択メニューの追加

プロジェクトのsrc/app/app.module.htmlを編集して、テーマの選択メニューを追加します。

    <span>Welcome</span>
    <div class="spacer"></div>
    <theme-picker></theme-picker>
画面にメニューが追加されます。

不要なコードのコメントアウト

とりあえず不要なコードをコメントアウトします。具体的には、src/_app-theme.scssと、src/styles/custom-themes/以下のscssについて、以下の部分をコメントアウトします。
src/_app-theme.scss

@import '~@angular/material/theming';
/*
@import './app/pages/component-category-list/component-category-list-theme';
@import './app/pages/component-sidenav/component-sidenav-theme';
@import './app/pages/component-viewer/component-viewer-theme';
 :
}
*/
// Define the light theme.
$primary: mat-palette($mat-indigo);
$accent:  mat-palette($mat-pink, A200, A100, A400);

$theme: mat-light-theme($primary, $accent);

deeppurple-amber.scss

@import '../../app-theme';

// Define the light theme.
$primary: mat-palette($mat-deep-purple);
$accent:  mat-palette($mat-amber, A200, A100, A400);

$theme: mat-light-theme($primary, $accent);
@include angular-material-theme($theme);
//@include material-docs-app-theme($theme);
indigo-pink.scss

@import '../../app-theme';

// Define the light theme.
$primary: mat-palette($mat-indigo);
$accent:  mat-palette($mat-pink, A200, A100, A400);

$theme: mat-light-theme($primary, $accent);
@include angular-material-theme($theme);
//@include material-docs-app-theme($theme);
pink-bluegrey.scss

@import '../../app-theme';
@import '../../highlightjs/material-dark';

// Define the dark theme.
$primary: mat-palette($mat-pink);
$accent:  mat-palette($mat-blue-grey);

$theme: mat-dark-theme($primary, $accent);
@include angular-material-theme($theme);
//@include material-docs-app-theme($theme);
purple-green.scss

@import '../../app-theme';
@import '../../highlightjs/material-dark';

// Define the dark theme.
$primary: mat-palette($mat-purple);
$accent:  mat-palette($mat-green, A200, A100, A400);

$theme: mat-dark-theme($primary, $accent);
@include angular-material-theme($theme);
//@include material-docs-app-theme($theme);

テスト

メニューからテーマを切り替えると、それに応じてMatToolbarの色が変わります。

公式サイトの説明

Angular Material公式サイトのテーマの動的変更に関する説明はこちらのページにあります。
Changing styles at run-time
https://material.angular.io/guide/theming#defining-a-custom-theme

このブログを検索

QooQ