[AngularMaterial] Sidenavの使い方を理解しよう!

2018/04/21時点の情報です。

AngularMaterialの基本

AngularMaterialの導入などの基本は次のサイトで解析しています。

導入は済んでいる前提でのサイドナビバー解説になります。

[Angular入門] Angular5 への Angular Materialの導入方法! – まんくつ

解説は、公式のSidenav | Angular Material

の翻訳をメインにしていきます。

demoも公式のものをコピペしているだけです。

Sidenavの基本

Angular Materialの『sidenav』は、

折りたたみ可能なサイドコンテンツを作ることができます。

2セットのコンポーネント(sidenavとdrawerコンポーネント)

によってサイドナビゲーションメニューバーはもちろん、

主要なコンテンツを組込んだサイドナビバーを設計することができます。

sidenav

sidenavコンポーネントから見ていきます。

sidenavコンポーネントは、

アプリケーションにサイドコンテンツを

追加するように設計されています。

sidenavの設定に次の三つのコンポーネントを使用します。

  • <mat-sidenav-container>
  • <mat-sidenav-content>
  • <mat-sidenav>

  • mat-sidenav-container:コンテンツの構造コンテナとして機能
  • m​​at-sidenav-content:メインコンテンツ
  • mat-sidenav:サイドコンテンツ

文章ではよくわからないともうのでDEMOをつくりました。

Basic sidenav

DEMO

上の画像とDEMOが最も単純なsidenavコンポーネントです。

HTMLとCSSは次のようになります。


このように、メインコンテンツもsidenav-containerに

組込む必要があります。

Sidenavという名前だけ見て、

既存のサイドナビバーをAngularMaterialに

変えれば動くだろうと軽く見ていると痛い目見ます。

drawer

drawerコンポーネントは、

アプリの小さな部分にサイドコンテンツを

追加するように設計されています。

これは、3つのコンポーネントを使用して実行されます。

  • <mat-drawer-container>
  • <mat-drawer-content>
  • <mat-drawer>

これらのコンポーネントは、

先程のsidenavの3つのコンポーネントと同様の役割です。

ただし、先述の通りアプリケーションの

全てに影響を与えない一部分に

サイドナビバーを表示するという違いはあります。

サイドコンテンツをアプリ全体に追加するのではなく、

サイドコンテンツをアプリの

小さなセクションに追加するように設計されています。

sidenavと殆ど全て同じ機能をサポートしていますが、

固定配置はサポートしていません。

position: absolute;等つかえないということですね。

このように、sidenavとdrawerには、

アプリ全体にサイドナビバーを入れたい → sidenav

アプリの一部にサイドナビバーを入れたい → drawer

という違いがあります。

アプリでどんなふうに使いたいかを

整理してから導入するほうが良さそうです。

メインとサイドコンテンツの指定

メインとサイドの両方のコンテンツは、

<mat-sidenav-container>

の内側に置く必要があります。

メインコンテンツの<mat-sidenav-content>は

<mat-sidenav-container>に一つしか持てません。

また、ヘッダやフッタのようなサイドナビバーの

影響を受けたくないコンテンツは、

コンテナの外側に置くことができます。

サイドのコンテンツは、

<mat-sidenav>

要素で囲む必要があります。

mat-sidenavのpositionプロパティは、

サイドコンテンツをメインコンテンツの

右端、左端をどちらに配置するか指定するのに使用できます。

左端に配置するstart(デフォルト)、右端がendのいずれかを設定します。

例:

また、<mat-sidenav-container>内には二つの

<mat-sidenav>を持つことができます。

もちろん、右端と左端のサイドナビバーの2つになります。

同じ端に二つのサイドナビバーを設定することはできません。

これらの同じ規則はすべて

drawerコンポーネントにも適用されます。

サイドナビバーの開閉

DEMO

<mat-sidenav>は、

open()close()toggle()メソッドを

使用してオープンまたはクローズできます。

例:(click)=”sidenav.toggle()”

これらのメソッドは、

openedプロパティにPromise<boolean>を返します。

sidenavが表示するとtrue、

非表示になるとfalseを返します。
表示状態は、openedプロパティを使用して

テンプレートのプロパティバインディングを介して

設定することもできます。

プロパティは、双方向バインディングをサポートします。

また、<mat-sidenav> は、オープンイベントとクローズイベントである

(opened)と(closed)プロパティそれぞれの出力プロパティもサポートしています。

これらのプロパティとメソッドはすべて、

<mat-drawer>でも動作します。

DEMOコード

対応するtsファイルのクラスに

events = [];もいります。

sidenavの表示方法を変える

DEMO

<mat-sidenav>は、

modeプロパティに基づいて

3つの異なる方法のいずれかでレンダリングできます。

Mode Description
over メインコンテンツにSidenavを重ねて表示
push Sidenavはメインコンテンツを押し出し、背景を覆い隠す
side Sidenavはメインコンテンツと並んで表示され、メインコンテンツの幅を縮小してsidenavのスペースを確保します

モードを指定しないと、デフォルトでoverが使用されます。

<mat-drawer>は、これらのすべてのモードをサポートしています。

DEMOコード

TSに

mode = new FormControl(‘over’);

app.moduleに

import { FormsModule, ReactiveFormsModule } from ‘@angular/forms’;
 も追加すれば動きます。

開いているサイドナビバーサイズを変更する

DEMO

デフォルトでは、レイアウト スラッシング を避けるために、

Sidenavは数回の重要な時点

(オープン時、ウィンドウのサイズ変更時、モード変更時)

でしかdrawer containerを測定してサイズ変更しませんが、

問題が発生する可能性があります。

アプリが開いている間に引き出しの幅を

変更する必要がある場合は、

autosizeオプションを使用して

drawer containerに測定を続けるよう指示できます。

このオプションは、

パフォーマンスの問題を引き起こす可能性があるため、

自己責任で使用する必要があります。

sidenavのサイズを設定する

<mat-drawer>は、これらのすべてのモードをサポートしています。

DEMOコード

TSに

sidenavshowFiller = false;
drawershowFiller = false;

も追加してください。

以下のAngularMaterialModuleが必要

import { MatRadioModule } from ‘@angular/material/radio’;

AppModuleに

import { FormsModule, ReactiveFormsModule } from ‘@angular/forms’;

サイドナビバーサイズを設定する

<mat-sidenav>と<mat-drawer>は、

デフォルトでそのコンテンツのサイズに適合します。

必要であれば幅はCSSを使って明示的に設定できます。

mat-sidenav {
width: 200px;
}

resizeイベントは(まだ)サポートされていないので、

パーセントベースの幅を避けてください。

固定位置のサイドナビバー

DEMO

<mat-sidenav>のみ、

固定の位置決めがサポートされています。

(<mat-drawer>はできません。)

fixedInViewportプロパティを

設定することで有効にすることができます。

さらに、上下のスペースは

fixedTopGapとfixedBottomGapで設定できます。

これらのプロパティは、

上下に追加するスペースのピクセル値を受け取ります。

DEMOコード

以下のAngularMaterialModuleが必要

  • MatToolbarModule
  • MatFormFieldModule
  • MatInputModule

モバイル&デスクトップのレスポンシブなレイアウトを作成する

DEMO

(DEMOは開発者モードでモバイルで見てみてください。)

以下翻訳ですが、何がいいたいのかわかりませんでした。

サイドナビバーは、

モバイルとデスクトップディスプレイでは、

しばしば動作が異なる必要があります。

デスクトップ上では、

コンテンツセクションを

スクロールするだけの意味があります。

しかし、モバイルでは、

本体がスクロールする要素であることがしばしばあります。

これにより、アドレスバーが

自動的に非表示になります。

サイドナビバーは、

どちらのタイプのデバイスにも合わせるために

CSSでスタイルを付けることができます。

と公式サイトの説明がありましたが、

一言でいうとPC版とモバイル版の

サイドナビバーの表示を変えたいなら

切り替える方法があるから紹介するよ。

みたいな感じです。

めっちゃ役立ちそうですが、

コード例もこれまでと比較にならないくらい

複雑になっています。

次のことを理解していないと扱えないでしょう。

  • LayoutModuleのMediaMatcher
  • lifecycle-hooksのngOnDestroy
  • MediaQueryList
  • Array .fill .map
  • changeDetectorRef

一つずつ簡単に見ていきましょう。

MediaMatcher

Layout | Angular Material

MediaMatcherは、

matchMediaをラップする下位レベルのユーティリティです。

このサービスはブラウザの違いを正規化し、

単体テストでは別のものに置き換えることができる。

便利なAPIとして機能します。

matchMediaメソッドを使用して、

MediaQueryListを取得できます。

MediaQueryList

MediaQueryList – Web APIs | MDN

上記サイトより引用。

MediaQueryListオブジェクトは、

ドキュメントに適用されたメディアクエリに関する情報を格納し、

メディアクエリの状態が変化したとき

(メディアクエリのテストが開始されたとき、またはtrueに評価されなくなったとき)

にリスナに通知を送信します。

これにより、定期的に値をポーリングするのではなく

メディアクエリーがいつ変化するかを検出するために

ドキュメントを観察することが可能になり、

メディアクエリーステータスに基づいてスタイルを

プログラムで変更することができます。

ngOnDestroy()

Angular – Lifecycle Hooks

ngOnDestroy()で

クリーンアップロジックを実行します。

これは、Angularがディレクティブを破棄する前に

実行する必要があるロジックです。

changeDetectorRef.detectChanges()

いろいろ変わったことを検出(めっちゃざっくり)

ここではディスプレイサイズが変わったことを検知している。

もっと知りたい方は次のサイトを参考にしてみてください。

日本語訳:Angular 2 Change Detection Explained – Qiita

Understanding Change Detection Strategy in Angular ← Alligator.io

この辺りは初心者が理解するには厳しいと思うので、

だいたいでいいと思います。

Array .fill .map

fill() メソッドは、

配列中の開始インデックスから

終了インデックスまでの要素を固定値で設定します。

Array.prototype.fill() – JavaScript | MDN

map() メソッドは、

与えられた関数を配列のすべての要素に対して呼び出し、

その結果からなる新しい配列を生成します。

Array.prototype.map() – JavaScript | MDN

実際にやっていること

表示を切り替えたいwidthを設定

this.mobileQuery = media.matchMedia(‘(max-width: 600px)’);

上記の条件に合うなら

mobileQuery.matchesにtrue,

そうでないらfalseが返る。

mobileQuery.matchesの値によって表示を返る。

例えば次のコードのように

3項演算でモード切り替え等行う。

[mode]=”mobileQuery.matches ? ‘over’ : ‘side'”

表示サイズが途中で変わることも想定し、

changeDetectorRef.detectChanges()を使う。

そして、変わったときはngOnDestroyで、

mobileQueryに格納された表示サイズを初期化して、

表示サイズを再取得。

完全にあっている自信はありませんが、

ざっとコードと動作をみればこの様な感じでしょう。

DEMOコード

また、以下のモジュールも必要

import { MatListModule } from ‘@angular/material/list’;

import { LayoutModule } from ‘@angular/cdk/layout’;

さいごに

まだ公式には3つの項目があります。

Reacting to scroll events inside the sidenav container

Accessibility

Troubleshooting

この辺りは何時かの私に託したいと思います。

ここまでで、お役に立てていればと。^^

シェアする

  • このエントリーをはてなブックマークに追加

フォローする