LoginSignup
23
19

More than 5 years have passed since last update.

Angular 2入門:NgModelに触れてみる[rc.5対応]

Last updated at Posted at 2016-08-19

こんにちは。いまいです。
Angular2がそろそろstableになるということで、触れてみる次第です。

私が初めてAngular JSと触れた時に一番印象的だったのは双方向バインディングだったような気がします。その双方向バインディングがAngular 2でどうなったのかを見てみたいと思います。


前提

下準備

基本的な環境、構成は「npm iしてAngular 2のHello World!を書くところまで」と同じですが、NgModelを利用するためにFormsModuleを読み込む必要があります。FormsModule@angular/formsにあるので、これをnpmで引っ張ってきます。

npm i --save @angular/forms

加えて、app.module.tsFormsModuleを加えます。

app.module.ts
import {NgModule} from "@angular/core";
import {BrowserModule} from "@angular/platform-browser";
import {AppComponent} from "./app.component";
import {FormsModule} from "@angular/forms"; // 追加

@NgModule({
  imports: [
    BrowserModule,
    FormsModule // 追加
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

ModelからViewへ

MVCモデルでいうModelからViewへ値を反映させてみます。

app.component.ts
// Componentを作成するため、`@angular/core`から`Component`をimportしてます。
import {Component} from "@angular/core";

// `@Component`という見慣れない書き方をしていますが、これはTypescriptが採用しているDecorator構文です。
// 今ではES7の仕様としても検討されています。(20160818時点でstage2)
// このDecoartor構文により、`AppComponent`クラスに`selector`、`template`のメタデータを付与することができます。
@Component({
  selector: "my-app",
  template: `
    <h1>{{title}}</h1>
    <input type='text' [value]="title">
  `
})
export class AppComponent {
  title: string = "Hello World";
}

[value]="title"と記述することで、AppComponentクラスで宣言しているtitle="HelloWorld"を、input要素のvalueというプロパティに反映させることできます。[target]="expression"bind-target="expression"もしくはtarget={{expression}}という記述で任意のProperty、Attribute、Style、Classに値をバインディングすることができます。[...]という表記にてインプットプロパティを意味しています。

ViewからModelへ

MVCモデルでいうViewからModelへ値を反映させてみます。

app.component.ts
import {Component} from "@angular/core";

@Component({
  selector: "my-app",
  template: `
    <h1>{{title}}</h1>
    <input type='text' (input)="title=$event.target.value">
  `
})
export class AppComponent {
  title: string = "";
}

(input)="title=$event.target.value"と記述していますが、ユーザーの入力によってinput eventが発火した時に、title<input>の値を反映させています。(event名)="expression"もしくは、on-event名="expression"という記述でEventをバインディングすることができます。(...)という表記にてアウトプットプロパティを意味しています。

双方向バインディング(ModelからViewへ、ViewからModelsへ)

今度は上の二つを、ModelからView、ViewからModelを実現してみます。

ややこしい書き方

app.component.ts
import {Component} from "@angular/core";

@Component({
  selector: "my-app",
  template: `
    <h1>{{title}}</h1>
    <input type='text' [value]="title" (input)="title=$event.target.value">
  `
})
export class AppComponent {
  title: string = "Hello World";
}

双方向バインディングを実現するにはそのまま[value] (input)を書けばいけます。しかし、まあめんどくさいですね。
Angular JSでは、ng-modelというDirectiveを利用していたかと思いますが、Angular 2ではNgModelというDirectiveが存在します。これを使って次はもっと簡潔に書きます。

楽な書き方

はい。本題です。NgModelを使って双方向バインディングを実現します。

import {Component} from "@angular/core";

@Component({
  selector: "my-app",
  template: `
    <h1>{{title}}</h1>
    <input type='text' [(ngModel)]="title">
  `
})
export class AppComponent {
  title: string = "Hello World";
}

これでもっと簡単に双方向バインディングを行えました。[(...)]という記法が特徴的ですね。公式サイトではこの記法をbanana in a boxと呼称していました。(確かにバナナがボックスに入っているような、、、)
これまでの話を踏まえるとインプットとアウトプットの両方を実現するという意味を読み取ることができるかと思います。
ちなみに、[(ngModel)]="title" <=> [ngModel]="title" (ngModelChange)="title=$event" <=> bindon-value="title"と書くこともできます。 インプットとアウトプットの両方のメソッドをあるというのは、データのバインディング方向を意識しているのがうかがえますね。

最後に

  • ここらへん()[]bind-on-などをパースしていますね。ソースを見ると理解が深まります。
  • [ngModel][ng-model][NgModel]と書いてもエラーが出て止まっちゃうので気をつけてください。
  • 今回のソースはGitHubにあげておきます。
23
19
2

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
23
19