SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

次世代Webアプリケーションフレームワーク「Angular」の活用

「Angular Material」で、「Angular」のWebページにMaterial Designを導入しよう

次世代Webアプリケーションフレームワーク「Angular」の活用 第21回

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

Angular Materialの利用例

 以下では、Angular MaterialのさまざまなUI部品からいくつか抜粋して、利用例を紹介していきます

入力フォーム用のUI部品を表示

 Angular Materialが提供する、テキストボックスやチェックボックスなどの入力フォーム用UI部品を、図3のサンプルで紹介します。それぞれのUI部品が、Material Design固有の外観や挙動(クリック時のアニメーションなど)を備えています。

図3:Angular Materialの入力フォーム用UI部品を表示するサンプル(p002-input)
図3:Angular Materialの入力フォーム用UI部品を表示するサンプル(p002-input)

 図3のUI部品は、リスト4の通り記述されています。

[リスト4]入力フォーム用UI部品の記述(p002-input/src/app/app.component.html)
<h3>テキストボックス</h3><!--(1)-->
<mat-form-field>
  <input matInput placeholder="名前">
</mat-form-field>
<h3>セレクトボックス</h3><!--(2)-->
<mat-form-field>
  <mat-label>得意な言語</mat-label>
  <mat-select placeholder="select">
    <mat-option value="c">C/C++</mat-option>
    <mat-option value="java">Java</mat-option>
    <mat-option value="javascript">JavaScript</mat-option>
    <mat-option value="swift">Swift</mat-option>
    <mat-option value="kotlin">Kotlin</mat-option>
  </mat-select>
</mat-form-field>
<h3>チェックボックス</h3><!--(3)-->
<mat-checkbox>Angularの経験あり</mat-checkbox>
<h3>スイッチ</h3><!--(4)-->
<mat-slide-toggle>この情報を公開する</mat-slide-toggle>
<h3>ラジオボタン</h3><!--(5)-->
<mat-radio-group>
  <mat-radio-button value="1" checked>iOS</mat-radio-button>
  <mat-radio-button value="2">Android</mat-radio-button>
</mat-radio-group>
<h3>ボタン</h3><!--(6)-->
<div class="button-container">
  <button mat-button>通常のボタン</button>
  <button mat-raised-button color="primary">影付きボタン</button>
  <button mat-stroked-button color="primary">枠線ボタン</button>
</div>

 テキストボックス(1)は、HTMLの<input>にmatInput属性(ディレクティブ)を設定して、Material Designを子要素に適用する機能を持つ<mat-form-field>で囲みます。複数行テキストボックス(<textarea>)も同様にできます。

 セレクトボックス(2)は、<mat-select>、<mat-option>で記述します。なお、Angular 7からは、HTMLの<select>や<option>でもMaterial Designのセレクトボックスを記述できるようになりました(連載第18回「フレームワークとツールの両面で完成度アップ! 「Angular」バージョン7の新機能」参照)。

 チェックボックス(3)は<mat-checkbox>で記述します。同じ機能をスイッチで実現する<mat-slide-toggle>(4)も利用できます。また、ラジオボタン(5)は、複数の<mat-radio-button>を、<mat-radio-group>で囲みます。

 ボタン(6)は、<button>にmat-button属性(ディレクティブ)を指定します。指定するディレクティブの種類でデザインが変化し、mat-raised-buttonなら影付きのボタン、mat-stroked-buttonなら枠線で囲まれたボタンになります。詳細は公式ドキュメントも参考にしてください。

選択できるサイドメニューを表示

 Angular Materialでは、ページ内要素のアニメーションや表示切り替えを行う機能が提供されています。ここではそのうち、Sidenavコンポーネントで実装したサイドメニューのサンプル(図4)を紹介します。ボタンをクリックすると左からサイドメニューが表示され、リストをクリックするとサイドメニューが閉じて、選択内容が画面に表示されます。

図4:Sidenavコンポーネントで実装したサイドメニューのサンプル(p003-nav)
図4:Sidenavコンポーネントで実装したサイドメニューのサンプル(p003-nav)

 ルートコンポーネントのテンプレートはリスト5の通りです。

[リスト5]図4のサンプルのテンプレート(p003-nav/src/app/app.component.html)
<mat-sidenav-container><!-- 全体をまとめるコンテナー ...(1)-->
  <mat-sidenav #nav mode="side"><!-- サイドメニュー ...(2)-->
    <mat-toolbar color="primary">
      <span>選択肢</span>
    </mat-toolbar>
    <mat-action-list> <!-- リスト表示 ...(3)-->
      <button *ngFor="let elem of listData" mat-list-item
        (click)="listSelected(elem);">{{elem}}</button>
    </mat-action-list>
  </mat-sidenav>
  <mat-sidenav-content> <!-- ページ本体 ...(4)-->
    <mat-toolbar color="primary">
      <span>Sidenavのサンプル</span>
    </mat-toolbar>
    <div class="content">
      <!-- ボタン ...(5)-->
      <button mat-raised-button color="primary" (click)="nav.open();">
        好きなスマホメーカーは?
      </button>
      <div>あなたの選択は:{{result}}</div><!-- 結果表示 ...(6)-->
    </div>
  </mat-sidenav-content>
</mat-sidenav-container>

 サイドメニューに対応する<mat-sidenav>(2)と、ページ本体に対応する<mat-sidenav-content>(4)を、<mat-sidenav-container>(1)の子要素にして記述します。

 <mat-sidenav>の属性に指定した「#nav」は、他の箇所から「nav」という名前で参照できるようにする指定です。また、mode属性はサイドメニューの動作モードで、「side」を指定すると、サイドメニューとページ本体を並べて表示します。ほかに、サイドメニューがページ本体にオーバーレイする「over」、サイドメニューがページ本体を右に押し出して表示する「push」の動作モードが指定できます。

 サイドメニュー内の<mat-action-list>(3)は、リストを表示するコンポーネントです。listData配列の内容を*ngForディレクティブで繰り返してリストに表示します。

 ページ本体には、サイドメニューを表示するボタン(5)と、選択結果の表示部(6)を記述します。ボタンクリック時、nav.openメソッドでサイドメニューを開きます。

 リスト5のテンプレートに対応する実装はリスト6の通りです。

[リスト6]リスト5に対応する実装(p003-nav/src/app/app.component.ts)
export class AppComponent {
  listData = [  // リストに表示する選択肢 ...(1)
    'Apple',
(略)
  ];
  result: string = '';   // 選択結果 ...(2)
  @ViewChild("nav") nav: MatSidenav;  // Sidenav ...(3)
  listSelected(value) { // リスト選択時の処理 ...(4)
    this.nav.close();
    this.result = value;
  }
}

 (1)はサイドメニューのリストに表示する選択肢、(2)は選択結果を格納する変数です。(3)は、ViewChildデコレーターを利用して、リスト5(2)のサイドメニューをnav変数で参照する記述です。リストクリック時の処理は(4)で、nav.closeメソッドでサイドメニューを閉じて、選択結果をresult変数に格納します。resultの内容はリスト5(6)で画面表示されます。

ダイアログを表示

 Angular Materialには、ダイアログやメッセージをWebページにオーバーレイして表示させる機能があります。本記事では、ダイアログのサンプル(図5)を説明します。名前を入力してボタンを押すとダイアログに名前が表示され、ダイアログに好きな食べ物を入力してOKボタンを押すと、ダイアログでの入力内容が元のページに反映されます。

図5:Angular Materialでダイアログを表示するサンプル(p004-dialog)
図5:Angular Materialでダイアログを表示するサンプル(p004-dialog)

 ルートコンポーネントのテンプレートはリスト7の通りです。(1)で、テキストボックスとダイアログ表示ボタンを記述します。(2)は、ダイアログから渡された入力結果(dialogAnswer)に値が設定されている場合だけ、回答を表示する記述です。

[リスト7]図5のサンプルのテンプレート(p004-dialog/src/app/app.component.html)
<h3>質問</h3><!--(1)-->
<mat-form-field>
  <input matInput placeholder="名前" [(ngModel)]="name">
</mat-form-field>
<div>
  <button mat-raised-button color="primary" (click)="showDialog();">
    質問ダイアログを表示
  </button>
</div>
<div *ngIf="dialogAnswer"><!--(2)-->
  <h3>回答</h3>
  {{name}}さんは「{{dialogAnswer}}」と回答しました。
</div>

 ダイアログ表示などの処理は、ルートコンポーネントにリスト8の通り実装します。

[リスト8]リスト7に対応する実装(p004-dialog/src/app/app.component.ts)
export class AppComponent {
  name: string = '';  // 入力する名前 ...(1)
  dialogAnswer: string = '';  // ダイアログから受け取る回答 ...(2)
  constructor(private dialog: MatDialog) { }  // コンストラクター ...(3)
  showDialog() { // ボタンクリック時の処理 ...(4)
    // ダイアログを表示 ...(5)
    const dialogRef = this.dialog.open(MyDialogComponent, {
      width: '300px',
      data: { name: this.name }
    });
    // 表示したダイアログが閉じられた時の処理 ...(6)
    dialogRef.afterClosed().subscribe(result => {
      this.dialogAnswer = result;
    });
  }
}

 (1)は画面で入力する名前、(2)はダイアログから受け取る回答を格納する変数です。コンストラクター(3)で、ダイアログを操作するMatDialogのオブジェクトdialogを、依存性注入で受け取っておきます。

 ボタンクリック時の処理(4)では、まず、dialog.openメソッド(5)でダイアログを表示します。第1引数は表示するダイアログのコンポーネント(後述)、第2引数はオプションで、ここではwidth(ダイアログの幅)とdata(ダイアログに渡すデータ)を指定します。dataには、画面で入力した名前nameを設定します。

 dialog.openメソッドの戻り値dialogRefは、表示されたダイアログに対応しており、メソッドを実行してダイアログに追加の設定ができます。ここではdialogRef.afterClosedメソッド(6)で、ダイアログが閉じられた時の処理を設定します。イベントハンドラーの変数resultには、ダイアログから渡された値が格納されるので、それをthis.dialogAnswerに代入して画面に表示させます。

 ダイアログ自体を表すMyDialogComponentコンポーネントのテンプレートは、リスト9の通りです。

[リスト9]MyDialogComponentのテンプレート(p004-dialog/src/app/my-dialog/my-dialog.component.html)
<h1 mat-dialog-title>{{data.name}}さんへ</h1><!-- タイトル ...(1)-->
<div mat-dialog-content><!-- ダイアログ内容 ...(2)-->
  <mat-form-field>
    <input matInput placeholder="好きな食べ物" [(ngModel)]="returnValue">
  </mat-form-field>
  <p>これでよろしいですか?</p>
</div>
<div mat-dialog-actions><!-- ダイアログ操作部 ...(3)-->
  <!-- キャンセルボタン ...(4)-->
  <button mat-button (click)="closeDialog();" cdkFocusInitial>
    キャンセル
  </button>
  <!-- OKボタン ...(5)-->
  <button mat-button [mat-dialog-close]="returnValue">
    OK
  </button>
</div>

 (1)がダイアログのタイトル、(2)が内容、(3)が操作部です。HTML要素にそれぞれ、mat-dialog-title、mat-dialog-content、mat-dialog-actions属性(ディレクティブ)を指定して、ダイアログのデザインを適用します。

 (4)はキャンセルボタンで、後述するcloseDialogメソッドを実行してダイアログを閉じます。(5)はOKボタンです。「[mat-dialog-close]="returnValue"」と設定しておくと、ボタンクリック時にresultValue変数の値がダイアログの呼び元(この場合、リスト8(6)のresult変数)に渡されます。

 MyDialogComponentコンポーネントの実装はリスト10の通りです。

[リスト10]MyDialogComponentの実装(p004-dialog/src/app/my-dialog/my-dialog.component.ts)
export class MyDialogComponent {
  constructor(  // コンストラクター ...(1)
    private dialogRef: MatDialogRef<MyDialogComponent>, // ダイアログ ...(2)
    @Inject(MAT_DIALOG_DATA) private data: any // 渡されたデータ ...(3)
  ) { }
  closeDialog() { // ダイアログを閉じる処理 ...(4)
    this.dialogRef.close();
  }
}

 コンストラクター(1)で、ダイアログに対応するdialogRef(2)と、呼び出し元から渡されたデータdata(3)を、依存性注入で受け取ります。呼び元から渡されるデータは、MAT_DIALOG_DATAという名前(DIトークン)で依存性注入されるため、受け取る時に「@Inject(MAT_DIALOG_DATA)」と指定します。キャンセルボタンでダイアログを閉じる処理(4)では、dialogRef.closeメソッドでダイアログを閉じます。

[補足]Angular MaterialとCDK

 Angular Materialでは、デザインに依存しない挙動や機能を、CDK(The Component Dev Kit)として別に提供しています。CDKの詳細は、公式ページを参照してください。CDKの利用例として、ドラッグアンドドロップやスクロールを実現する方法を、連載第18回「フレームワークとツールの両面で完成度アップ! 「Angular」バージョン7の新機能」で紹介しています。

まとめ

 本記事では、Googleのデザインガイドライン「Material Design」に対応したAngularのUI部品コンポーネント「Angular Material」を紹介しました。Angular Materialを利用すれば、WebページをMaterial Designに対応させて、見た目や使い勝手を向上できます。

 次回は、CSSフレームワークBootstrapに準拠したUI部品をAngularに提供する「Angular powered Bootstrap」を紹介します。

参考資料

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
次世代Webアプリケーションフレームワーク「Angular」の活用連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト  吉川 英一(ヨシカワ エイイチ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/11516 2019/05/13 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング