HTML5テクニカルノート
Angular 2入門 01: 編集ページをつくる
- ID: FN1611005
- Technique: HTML5 / JavaScript
- Package: Angular 2.1
「Angular 2入門」シリーズはAngular公式サイトの「TUTORIAL」をもとに、説明の仕方や進め方を手直ししたものです。コードの動きは段階を細かめに分けて確かめるようにし、TypeScriptの構文についても補いました。基本的な機能であるデータバインディングについてご説明します。Angular 2をよく知らなかったり、まだ環境ができていない方は、「Angular 2: とにかくAngular 2でコードを書いて動かす」を先に読まれるとよいでしょう。
01 もとにする作例ファイル
本稿の解説は、前出「Angular 2: とにかくAngular 2でコードを書いて動かす」でつくったファイル(コード001およびコード002)に手を加えるかたちで進めます(中身はAngular公式サイトの「QUICKSTART」と同じです)。ファイルの構成は、つぎの図001のとおりです。プロジェクトのフォルダの名前は、どのように変えても構いません。
図001■「Angular 2: とにかくAngular 2でコードを書いて動かす」でつくったファイル構成
02 HTMLドキュメントを書き替える
まず、HTMLドキュメント(index.html)は以下のコード001のように書き替えます。もとのファイルと組み立てはほぼ同じです。変わったのは第1に、JavaScriptライブラリ4つをCDN(unpkg)から読み込んでいます。サーバーで試すときも、ライブラリのアップロードは要りません。比較的大きいのが第2として、systemjs.config.jsをCDNのsystemjs.config.web.jsに替えたことです。もとの作例より、使うパッケージが増えました。さらに、初期設定のコードも含み、アプリケーションのモジュール(app.module)を直に起ち上げています。そのため第3に、systemjs.config.jsだけでなく、アプリケーションを起動するmain.tsも要らなくなりました。
コード001■アプリケーションを動かすHTMLドキュメント
index.html
<!DOCTYPE html>
<html>
<head>
<title>Angular Tour of Heroines</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<script src="https://unpkg.com/core-js/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js@0.6.25?main=browser"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.8"></script>
<script src="https://unpkg.com/systemjs@0.19.39/dist/system.src.js"></script>
<script src="https://cdn.rawgit.com/angular/angular.io/74ef87f/public/docs/_examples/_boilerplate/systemjs.config.web.js"></script>
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>
なお、CSSファイル(styles.css)については、もとのファイルをそのまま用います。
03 コンポーネントのクラスに定めたプロパティの値を要素に差し込む
つぎに、コンポーネントのクラス(AppComponent)に、つぎのようにプロパティ(titleとheroine)を加えます。この値は、クラスのデコレータに定めたComponent
関数に引数のオブジェクトを渡すとき、テンプレート(template
)の値の中で参照できます。その場合、二重波括弧{{}}
でプロパティをくくって加えます。ビルドしてアプリケーションを試すと、以下の図002のようにコンポーネントのクラスのプロパティ値が、差し込まれた要素のテキストとして示されます。
app.component.ts@Component({ template: '<h1>{{title}}</h1><h2>{{heroine}}の情報</h2>' // '<h1>Hello Angular!</h1>' }) export class AppComponent { title = 'ヒロイン一覧'; heroine = 'シータ'; }
図002■コンポーネントのクラスのプロパティ値が要素のテキストに差し込まれた
なお、デコレータ関数(Component)は渡された引数にもとづいて、そのあとに宣言されたクラス(AppComponent)を実行時に処理します(「TypeScript入門 12: デコレータ(Decorator)を使う」参照)。また、export
はファイルに分けたモジュールを、別のモジュールから使えるようにする仕組みです。他のモジュールは、使いたいモジュールとその宣言(クラスや関数など)をimport
します(「TypeScript入門 10: モジュール ー exportとimport」参照)。
プロパティに与えるのをオブジェクトにすれば、複数の値が含められます。そこで、つぎのように新たなクラス(Heroine)を定め、そこにプロパティ(idとname)を加えました。そして、コンポーネントのクラス(AppComponent)のプロパティ(heroine)は、その型づけにしてオブジェクトを与えています。もっとも、そのオブジェクトは新しいクラスのインスタンスではありません。TypeScriptでは、クラスを継承しなくても、オブジェクトに同じ型のプロパティが揃っていれば互換性は認められるのです(「TypeScript入門 08: 型の互換性」参照)。アプリケーションから表示されるページは、とくに変わりありません(前掲図002)。
app.component.tsexport class Heroine { id: number; name: string; } @Component({ template: '<h1>{{title}}</h1><h2>{{heroine.name}}の情報</h2>' // '<h1>{{title}}</h1><h2>{{heroine}}の情報</h2>' }) export class AppComponent { // heroine = 'シータ'; heroine: Heroine = { id: 1, name: 'シータ' }; }
04 コンポーネントのテンプレートに値の入ったラベルとテキスト入力フィールドを加える
さらに、コンポーネントのテンプレートに要素を加えます。デコレータ関数(Component)の引数オブジェクトに定めるtemplate
に、つぎのようにタグを書き足せばよいでしょう。ただ、改行もインデントもないので、要素が増えるとかなり見にくくなります。
template: '<h1>{{title}}</h1><h2>{{heroine.name}}の情報</h2><div><label>番号: </label>{{heroine.id}}</div><div><label>名前: </label><input value="{{heroine.name}}" placeholder="名前"></div>'
TypeScriptでは、ECMAScript 2015(ES6)のTemplate literal(テンプレートリテラル)が使えます。クォーテーションの替わりにバックティック(`
)でくくれば、空白文字が無視されるので、つぎのようにHTMLのタグと同じく書式を整えることができます。
@Component({ template: ` <h1>{{title}}</h1> <h2>{{heroine.name}}の情報</h2> <div><label>番号: </label>{{heroine.id}}</div> <div> <label>名前: </label> <input value="{{heroine.name}}" placeholder="名前"> </div> ` // '<h1>{{title}}</h1><h2>{{heroine.name}}の情報</h2>' })
二重波括弧{{}}
の参照は、前掲コードのように要素のテキストだけでなく、属性値に用いることもできます。アプリケーションをビルドして試すと、コンポーネントから差し込まれる要素にラベルやテキスト入力フィールドが加わり、コンポーネントのクラス(AppComponent)のプロパティから得られた値が示されます(図003)。クラスのデータを要素に反映することは「バインディング」といいます。
図003■コンポーネントから差し込まれる要素にラベルとテキスト入力フィールドが加わった
加えたテキスト入力フィールドのテキストは、キーボードから書き替えられます。けれど、今のところはページに示される情報に反映はされません。データはテンプレートの要素の側から参照する一方向に定められているからです。
05 編集されたテキストをコンポーネントに反映する
テキスト入力フィールドに打ち込んだテキストを、コンポーネントのクラスのプロパティ値に反映させるには、つぎのようにAngular 2のモジュールからFormsModule
クラスをimport
します。そして、アプリケーションのクラス(AppModule)のデコレータ(@NgModule)宣言に渡す引数のオブジェクトに、プロパティimports
の配列要素として加えます。
app.module.tsimport {FormsModule} from '@angular/forms'; @NgModule({ imports: [ BrowserModule, FormsModule ], }) export class AppModule {}
FormsModule
クラスのNgModel
ディレクティブを使うと、双方向のバインディングができます。コンポーネント(AppComponent)のテンプレート(template
)は、値をつぎのように書き替えます。要素(input)の属性(value)は[()]
でくくったディレクティブで替え、プロパティの参照を文字列で定めます。プロパティは{{}}
でくくらないことにご注意ください。
app.component.ts@Component({ template: ` <input
value[(ngModel)]="{{heroine.name}}" placeholder="名前"> ` }) export class AppComponent { }
アプリケーションをビルドして確かめると、テキストフィールドに入力したテキストでコンポーネントのクラスのプロパティ値が書き替わり、その値を参照する他の要素の表示に反映されます(図004)。ここまで書き上げたアプリケーションとコンポーネントのモジュールは、以下のコード002にまとめました。併せて、Plunkerに作例のコードを掲げています。
図004■テキスト入力フィールドに打ち込んだテキストが他の要素の表示に反映される
コード002■アプリケーションとコンポーネントのモジュール
app.module.ts
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {FormsModule} from '@angular/forms';
import {AppComponent} from './app.component';
@NgModule({
imports: [
BrowserModule,
FormsModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
import {Component} from '@angular/core';
export class Heroine {
id: number;
name: string;
}
@Component({
selector: 'my-app',
template: `
<h1>{{title}}</h1>
<h2>{{heroine.name}}の情報</h2>
<div><label>番号: </label>{{heroine.id}}</div>
<div>
<label>名前: </label>
<input [(ngModel)]="heroine.name" placeholder="名前">
</div>
`
})
export class AppComponent {
title = 'ヒロイン一覧';
heroine: Heroine = {
id: 1,
name: 'シータ'
};
}
- Angular 2: とにかくAngular 2でコードを書いて動かす
- Angular 2入門 02: リストを加える
- Angular 2入門 03: コンポーネントを分ける
- Angular 2入門 04: サービスをつくる
- Angular 2入門 05: Routerを使う
- Angular 2入門 06: HTTPサービスでデータを取得・保存する
- Angular 2入門 07: HTTPサービスでデータを追加・削除する
- Angular 2入門 08: HTTPサービスが返すObservableを使ったデータの検索
作成者: 野中文雄
作成日: 2016年11月14日
Copyright © 2001-2017 Fumio Nonaka. All rights reserved.