Angular 4 でマテリアルデザインを使う


Angular 4 で、マテリアルデザインを適用してアプリを作ろうと思ったんだけど、無茶苦茶にハマったので、ちゃんと動く手順をメモしておく。

ハマった方法

私は、Angular の初心者なので、何から始めたらいいのかわからず、本に書いてある通り、quick-start のリポジトリを元に、material design の npm  を追加しました。すると、バージョン問題が発生するので、ちゃんとバージョンを合わせたり、ライブラリのバージョンが違うので、ディレクトリが違うため、systems.config.js にライブラリを追記したりと、色々やりましたが、ライブラリ取得時の404エラーは治ることなく、数時間格闘しましたが無理なので、寝ました。

うまくいく方法

 しかし、問題は、「quick-start」を元にしているからであって、複雑なことを減らすとうまくいくようです。(特に初心者はいきなりたくさんのことを学べないので)現時点でうまく行った方法をシェアします。

基本的には Resource のコーナーで書いて置いた方法のミックスです。

Angular CLI を入れる

Angular CLI を入れます。

npm install -g @angular/cli

マテリアルデザインのテンプレートを生成する

Angular 4 Material Tutorial に従って、マテリアルデザインの Angular4 のテンプレートがあるので、それを使います。ライブラリの依存問題は、時間がかかるので楽な方法で。

ng new ng4-material

マテリアルデザインのnpm を追加

マテリアルデザインのライブラリを追加していきます。ポイントは、cdkを先に追加しないとうまくいきません。

$ npm install --save @angular/cdk
$ npm install --save @angular/material @angular/animations

hammerjs も入れておきます。md-slide-toggle, md-slider, mdTooltipは、hammerjs に依存しているので、入れとく方がいいでしょう。

$ npm install --save hammerjs

そして、src/main.ts に追加しておきます。

import 'hammerjs';

ライブラリの組み込み

npm で入れたライブラリを組み込んでいきます。

style の追加

src/style.css にお好みのスタイルを追加します。アイコンも加えてこんな感じで。body 以降はオプションですが、最初の二行がポイントです。アイコンを取得するのと、インポートしたマテリアルデザインのテーマをインポートしています。

@import '~https://fonts.googleapis.com/icon?family=Material+Icons';
@import '~@angular/material/prebuilt-themes/indigo-pink.css';

body {
    margin: 0;
    font-family: Roboto, sans-serif;
  }

  md-card {
    max-width: 80%;
    margin: 2em auto;
    text-align: center;
  }

  md-toolbar-row {
    justify-content: space-between;
  }

  .done {
    position: fixed;
    bottom: 20px;
    right: 20px;
    color: white;
  }

index.html

特に何もしなくても大丈夫ですが、アイコンインポートしています。(多分不要)

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Ng4Material</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
  <app-root></app-root>
</body>
</html>

Material の追加

material.module.ts にまとめて、マテリアル関係のインポートを書いておきます。

import { NgModule } from '@angular/core';

import {
  MdButtonModule,
  MdMenuModule,
  MdToolbarModule,
  MdIconModule,
  MdCardModule
} from '@angular/material';

@NgModule({
  imports: [
    MdButtonModule,
    MdMenuModule,
    MdToolbarModule,
    MdIconModule,
    MdCardModule
  ],
  exports: [
    MdButtonModule,
    MdMenuModule,
    MdToolbarModule,
    MdIconModule,
    MdCardModule
  ]
})
export class MaterialModule {}

app.module.ts

先ほどのマテリアルデザインのインポートを読み込んでいます。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { MaterialModule } from './material.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    MaterialModule,
    BrowserAnimationsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.html

あとは、マテリアルデザインを使って、読み込まれる html を作成す流だけ。

<div>
  <md-toolbar color="primary">
    <span><md-icon>mood</md-icon></span>

    <span>Muscke Hack</span>

    <button md-icon-button [md-menu-trigger-for]="menu">
      <md-icon>more_vert</md-icon>
    </button>
  </md-toolbar>
  <md-menu x-position="before" #menu="mdMenu">
    <button md-menu-item>Option 1</button>
    <button md-menu-item>Option 2</button>
  </md-menu>

  <md-card>
    <button md-button>All</button>
    <button md-raised-button>Of</button>
    <button md-raised-button color="primary">The</button>
    <button md-raised-button color="accent">Buttons</button>
  </md-card>

  <span class="done">
    <button md-fab>
      <md-icon>check circle</md-icon>
    </button>
  </span>
</div>

あとは実行

npm start

まとめ

ng new ng4-material のテンプレートを使うとアホみたいに簡単にできました。quick-start のテンプレートを使うから酷い目にあったようです。本当は、quick-start は、テストとか色々な環境が揃っているので、こちらを元にしたかったのですが、これなら、こちらを元にして、テストを足した方が楽そうです。

やはり、依存性の問題を解決するのは時間がかかるので、そこに当たらないテンプレートを使った方がいいと感じました。さ、やっとコーディングだ。

Resource