元のサイトはこちら。かなり端折っていますが一応日本語版です。
第2章ではアプリを実際に作ります。 チュートリアルでは開発をローカルで進めていますが私はWindowsユーザでローカル開発が苦痛なのでAmazon Linux上で進めます。
アプリの作成
cd ng new angular-tour-of-heroes
これでangular-tour-of-heroesディレクトリ以下にアプリのファイルが生成されます
アプリの起動
念のため起動して動くかどうか確認しましょう:
cd angular-tour-of-heroes ng serve --host=0.0.0.0 --public=グローバルIP
ブラウザでhttp://グローバルIP:4200/をアクセスするとQuickStartと同じ画面が表示されるはずです。
ターミナルをもう1つ開く
ターミナルをもう1つ開きます。なぜもう1つ開くかというと、1つ目はng serveが実行していてソース編集に使えないためです。 こちらでアプリのappディレクトリに移動します:
cd ~ cd angular-tour-of-heroes/src/app
app.component.tsの編集
まず、アプリで表示しているHTMLを変更します。 app.component.tsを開くと、次のようになっているはずです:
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; }
まず、templateUrlの行を消し、代わりにtemplateを定義します。 その際、バッククオートを使ってタグを括ってください(シングルクオートでも動作しますが)
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: `<h1>{{title}}</h1><h2>{{hero}} details!</h2>`, styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; }
次にAppComponent classの中において、titleを定義していますが、これを変更し、かつ、heroという変数を追加します:
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: `<h1>{{title}}</h1><h2>{{hero}} details!</h2>`, styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Tour of Heroes'; hero = 'Windstorm'; }
これで保存します。1つ目のターミナルでコンパイルが走りますので、エラーがなければブラウザを開いてhttp://グローバルIP:4200/を確認します:
templateの中の{{ }}はAngularの補完バインドシンタックスです。 コンポーネント内のtitleとhero属性をHTMLのタグの中で文字列として表現します。
Heroオブジェクトの作成
我々のヒーローにIDと名前を与えることにします。app.component.tsにHeroクラスを追記します:
import { Component } from '@angular/core'; export class Hero { id: number; name: string; } @Component({ selector: 'app-root', template: `<h1>{{title}}</h1><h2>{{hero}} details!</h2>`, styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Tour of Heroes'; hero = 'Windstorm'; }
次に、AppComponentクラスの中で、hero属性をHero型に変更します。その際、id=1、name=Windstormで初期化します:
import { Component } from '@angular/core'; export class Hero { id: number; name: string; } @Component({ selector: 'app-root', template: `<h1>{{title}}</h1><h2>{{hero}} details!</h2>`, styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Tour of Heroes'; hero: Hero = { id: 1, name: 'Windstorm' }; }
ここでブラウザを開き再読込をすると次のような画面になるはずです:
タイトルは正常に表示されますが、ヒーローの名前は[object Object]となっています。 これは、AppComponentにおける heroをstringからオブジェクトに変えたにも関わらず、 templateにおいて {{ hero }}と参照しているためです。
そこで、templateで名前を参照するよう、{{ hero }} から {{ hero.name }} に変更します:
import { Component } from '@angular/core'; export class Hero { id: number; name: string; } @Component({ selector: 'app-root', template: `<h1>{{title}}</h1><h2>{{hero.name}} details!</h2>`, styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Tour of Heroes'; hero: Hero = { id: 1, name: 'Windstorm' }; }
ブラウザを再読込すると、名前が正しく表示されるようになっているはずです。
次に、ヒーローのidとnameを表示するためのHTMLをtemplateに定義します。その際、HTMLを複数行をまたいで記載します。`(バックティック)を使用しているのは、複数行の記載を可能にするためです。これはES2015/TypeScriptのテンプレートリテラルの機能です。
template: `<h1>{{title}}</h1> <h2>{{hero.name}} details!</h2> <div><label>id: </label>{{hero.id}}</div> <div><label>name: </label>{{hero.name}}</div> `,
編集後のソースはこうなります:
import { Component } from '@angular/core'; export class Hero { id: number; name: string; } @Component({ selector: 'app-root', template: `<h1>{{title}}</h1> <h2>{{hero.name}} details!</h2> <div><label>id: </label>{{hero.id}}</div> <div><label>name: </label>{{hero.name}}</div> `, styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Tour of Heroes'; hero: Hero = { id: 1, name: 'Windstorm' }; }
ブラウザをリロードするとこのようになっているはずです:
次に、ヒーローの名前を編集可能にします。編集した名前は即座に表示に反映させたいとします。
そこでtemplateの中の名前を表示する部分を以下のように変更します:
- <h2>{{hero.name}} details!</h2> + <div> + <label>name: </label> + <input [(ngModel)]="hero.name"> + </div>
ngModelは、hero.name属性をこのテキストボックスにバインドします。テキストボックスへの変更はhero.name属性に反映され、hero.name属性への変更はテキストボックスに反映されます。
さて、このままではブラウザを開いても何も表示されないはずです。Chromeの場合、Ctrl+Shift+Iを教えてデベロッパーコンソールを開いてみてください。次のエラーが表示されているはずです:
原因はngModelです。これはAngularにおける妥当な記述ですが標準では読み込まれてないのです。 そこで、app.module.tsファイルを編集します。
まず、3行目あたりに次を追記します:
import { FormsModule} from '@angular/forms'; // <-- ngModelが含まれている場所
さらに@NgModuleディレクティブのimportsに次を追記します:
FormsModule // <-- [(ngModel)]とバインドする前にFormsModuleをインポートする
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule} from '@angular/forms'; // <-- ngModelが含まれている場所 import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, FormsModule // <-- [(ngModel)]とバインドする前にFormsModuleをインポートする ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
これでブラウザを開きリロードすると次の画面が表示されると思います。 入力欄を編集すると、編集結果がnameの後に表示されるはずです:
importを記載し、かつ、importsに記載している理由は、私の推測ですが、 最初のimportはTypeScriptにおけるライブラリの追加。そして2つめのimportsが Angularにおけるライブラリの追加なのだと思います。
まとめ
本章では次を行いました: