LoginSignup
3
4

More than 5 years have passed since last update.

Angular 4 でマテリアルデザインを使う データバインディング編

Posted at

前回の投稿 Angular 4 でマテリアルデザインを使うで、とりあえずインストールまでできたので、次に、データのバインディングをマテリアルデザインを適用しながらやってみたい。

最初の落とし穴

Angular4 と マテリアルデザインのインストールのブログはあっても、なかなか、Angular 4 のバインディングと一緒に書いている記事は見当たらなかった。多分みんな慣れているからだろう。マテリアルデザインも、Angular も同時に初心者の人はあまりやらないのかな。そこで、何かを参考に基本的なことをやるわけですが、ここで強烈にはまったのが、プロジェクト間違い。

という事実だ。最初間違えて AngularJS Material を参考にコードを書いてたら、モジュールが見つからないとか出てきて、初心者の私は死亡、もう、REACT にしようかなぁとか頭によぎった。エラーをググってみると、「AngularJS Material と、Angular Materialは別プロジェクト」ということが書いてあった。、、、ムッチャややこしいわ。ちなみに、「AngularJS Material」 はどうやら、Angular 1.x向けのよう。だから、我々は、基本的にAngular Material を参考にすると良い。基本的にドキュメントは丁寧なのでわかりやすい。

フォームの作成

まずは基本的なフォームを作ろうとしている。それをバインディングしてみる。

"Please add a @NgModule annotation" error

最初にやっていると当たったエラー。JavaScript のエラーは理由がよくわからないのも多いなぁ。

詳細は上記の記事だけど、具体的には、tsconfig.jsonpath のエントリを追加する。angular-cli を使っているプロジェクトだと、Linked librariesというのが必要らしく、コンパイルの時のリンクのパスをtsconfig.jsonに指定する必要がある。このエラーメッセージからは到底わからないのが辛いところ。

    "paths": {
      "@angular/*": [
        "..node_modules/@angular/*"
      ]
    },

インプットフォームの作成

とりあえず、食事を入力するフォームを作ってみる。まずは、ドメインクラスの定義

export class Food {
    name: string;
    date: Date;
    calorie: number;
    protein: number;
    carb: number;
    fat: number;
    meal_kind: FoodType;
}

簡単のため、まずは、名前と日付程度を試してみる。


@Component({
  selector: 'app-root',
  templateUrl: './food-detail.component.html'
})
export class FoodDetailComponent {
  food: Food;
  constructor() {
    this.food = new Food();
    this.food.name = "Taro";
    this.food.date = new Date();

  }

  title = 'Muscle Hack';
}

テキスト入力

テキスト入力を可能にするためには、

が参考になる。テキスト入力のコンポーネントを使うためには、上記のページの API に書いている通り、import {MatInputModule} from '@angular/material'; を追加する。具体的には下記の通り。前回の記事の通り、私は、material.module.ts という名前で、マテリアル系のインポートは分離している。

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

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

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

通常の入力フォームはこんな感じでいける。バインディングは、通常の、Angular の時と同じ。
私は、Angular Example - Tour of Heroes: Part 6とかを参考に書いている。

    <md-form-field class="example-full-width">
        <input mdInput placeholder="Name" name="name" [(ngModel)]="food.name" disabled value="Ushio">
    </md-form-field>

これだと、極めてそっけない画面になる。これは悲しい。

Screen Shot 2017-10-01 at 6.47.19 PM.png

もう少し見栄えを良くしたい。じゃあ、とりあえず、ツールバーをつけてみよう。

<md-toolbar colo="primary">
        <span>Msucle Hack</span>
    </md-toolbar>
    <md-form-field class="example-full-width">
        <input mdInput placeholder="Name" name="name" [(ngModel)]="food.name" disabled value="Ushio">
    </md-form-field>

Screen Shot 2017-10-01 at 6.49.05 PM.png

ぐぬぬ。地味だ、思った色と違う。なんでや!と思ったけど、単にtypo. color

<md-toolbar color="primary">

やっと思った色に。

Screen Shot 2017-10-01 at 6.50.48 PM.png

しかし、まだまだ、ダサい、なんかサンプルと違う。そうだカードを入れてみよう。

それっぽくなった。

Screen Shot 2017-10-01 at 6.52.29 PM.png

Date Picker

次に Date Picker をつけてみたい。やっぱ日付は、部品があるので使いたい。

を同じく参考にする。ただし、今回は、このページの API で必要とされているモジュール以外にも必要になるモジュールが存在した。
MdNativeDateModule だ。同じく、material.module.ts の記述はこう変わった。

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

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

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

次に、food-detail.compent.html を書き換える

<md-toolbar color="primary">
        <span>Msucle Hack</span>
    </md-toolbar>

    <md-card>
    <form class="example-form">
        <md-form-field class="example-full-width">
            <input mdInput placeholder="Name" name="name" [(ngModel)]="food.name" disabled value="Ushio">
        </md-form-field>
        <md-form-field>
            <input mdInput [(ngModel)]="food.date" name="date" [mdDatepicker]="myDatepicker">
            <md-datepicker-toggle mdSuffix [for]="myDatepicker"></md-datepicker-toggle>
            <md-datepicker #myDatepicker></md-datepicker>
        </md-form-field>
    </form>
    </md-card>

こちらのハマりどころは、先ほどのライブラリの追加ぐらいで特にない。ちなみに、md-datepicker-toggle から、mdSuffix を抜くと見栄えがおかしくなるので、mdSuffixをつけて、場所を調整すること。

うむ。それっぽい。バインディングもしっかりできている。

Screen Shot 2017-10-01 at 7.02.54 PM.png

うーん。しかし、日本的には表示が違うかな。ロケールを指定しよう。material.module.ts のところに、次の記述を追加。

  providers: [
    {provide: MAT_DATE_LOCALE, useValue: 'ja-JP'},
  ],

もしくは、food-detail.component.ts のFoodDetailComponent を次のようにする。

export class FoodDetailComponent {
  food: Food;
  constructor(dateAdapter: DateAdapter<NativeDateAdapter>) {
    dateAdapter.setLocale('ja-JP');
    this.food = new Food();
    this.food.name = "Taro";
    this.food.date = new Date();

  }

試すとどちらでも動作した。

Screen Shot 2017-10-01 at 7.17.38 PM.png

まとめ

久々に、JavaScript のフロントエンドを触ったが、やっぱデバッグが面倒だ。デバックメッセージからストレートに意味が取れないことが多い。やっぱり、npm start をして、部品を一つ一つ追加していって、動くのを確認する方が良さげ。というのも、何かを追加したら、画面が出なくなってガサーとエラーがはかれるわけだけど、部品ごとに区切らないと、デバッグがしにくい。これがちょっとした学び。

次は、enum を使って、選択肢を作ってみたいな。

リソース

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4