かえるの井戸端雑記

開発日誌的な記事だったり備忘録だったり。まとめ記事と言うよりは、七転八倒の様子を小説みたいに読んで眺めてもらえればと。

Angular2を使ってみる 5. Counter作り

なにをやってみようか

一通り導入までの勉強はしたので自分でもいじってみようと思う。でも何をいじろうか。

考えたけど、以下の2つを実施することにする。

  1. fileの再配置(srcとdistの分離)
  2. buttonを押したらcount upするだけの簡単なcomponentの作成

これらが終わったらRxJSを使うような処理も入れてみたいなあ。今のところこれといって作りたいapplicationがあるわけではないので、どこにたどり着くのかは僕にもわからない。知らない技術の実験的な感じで終わるかも。あ、lessとかstylusと言われているものも使いたい。

環境整理

ではまず環境整理。fileの再配置(srcとdistの分離)をする。

まずindexにある*.jsを削除して、と。./srcにindex.htmlを配置。で、どうしようかな。とりあえず今はこんな感じ。

% tree -I node_modules
.
├── Makefile
├── README.md
├── app.component.ts
├── app.module.ts
├── hello-world.component.ts
├── index.ts
├── package.json
├── src
│   └── index.html
└── tsconfig.json

うーん。typescriptのfileをsrcに移動しよう。これで準備は出来た。あとはbuildのparameterを変えて、dist/以下に配置されるようにする。Makefileからmake buildで呼び出すつもりなので、dirがなければ作るようにそちらに書き込み。

あ。typescriptのcompileという行程があった。こっちは出力先指定できるかな。

-outDir DIRECTORY Redirect output structure to the directory.

あったあった。

npm ERR! angular2@1.0.0 tsc: `tsc -p ./src --outDir ./dist`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the angular2@1.0.0 tsc script 'tsc -p ./src --outDir ./dist'.

怒られた。駄目なの?

stackoverflow.com

いやいけそうな気がする。

ああ違った。fileを再配置した時点でcompileが通らなくなっている。tsconfig.jsonをいじってあげないといけないんだ、たぶん。

filesやoptionをいじってみた。これでどうだろう。

無事通った。

これでmake cleanすると、

% tree -I node_modules
.
├── Makefile
├── README.md
├── package.json
├── src
│   ├── app.component.ts
│   ├── app.module.ts
│   ├── hello-world.component.ts
│   ├── index.html
│   └── index.ts
├── tmp
└── tsconfig.json

make buildすると、

% tree -I node_modules
.
├── Makefile
├── README.md
├── build
│   ├── app.component.js
│   ├── app.module.js
│   ├── hello-world.component.js
│   └── index.js
├── dist
│   ├── bundle.js
│   └── index.html
├── package.json
├── src
│   ├── app.component.ts
│   ├── app.module.ts
│   ├── hello-world.component.ts
│   ├── index.html
│   └── index.ts
└── tsconfig.json

という感じに生成されるようになった。

……htmlは最初からdistでもいい気がしてきた。ちなみにmake buildする都度にdistやbuildはrm -dされるお気楽仕様。

componentの追加

次にcount upのcomponentを追加しよう。いやNgModuleだっけ?

今回の目標としては<my-counter></my-counter>のようなものを入れ込んで、まずはそこに数値を表示させるまで。その次にformとしてのbuttonをいれて、その次にeventを組み込み、最後に<my-counter>に反映させるというところまで……結構手順あるな。

さてどうすればいいんだろう。app.module.tsに追加してもいいけど作る物としては全然別物でhello worldと依存関係があるわけでもないからmoduleとしては分けておこうか?

いや違うか。ここにBrowserModuleがある以上ここがbrowser処理の最初のはず。だからここのbootstrapとdeclarationsにcomponentを追加する感じか。

counter.component.ts

まずはcounter.component.tsを作ってみる。ほぼhello-world.component.tsと同じ。selectorとtemplateを少し変えてみた。

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

@Component({
    selector: 'my-counter',
    template: `
    <h2>Counter:0</h2>
`
})
export class CounterComponent {}

app.module.ts

次にapp.module.tsにCounterCompoerntを入れ込む。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { HelloWorldComponent } from './hello-world.component';
import { CounterComponent } from './counter.component';


@NgModule({
    imports: [
    BrowserModule
    ],
    declarations: [
    AppComponent,
    HelloWorldComponent,
    CounterComponent
    ],
    bootstrap: [
    AppComponent,
    CounterComponent
    ]
})
export class AppModule {}

app.component.ts

これでいいかと思ったけどいや<my-counter>をまだどこにも埋め込めてないよ。どこだっけ。調べてみたらapp.component.tsだった。

ここに適当に入れ込む。

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

@Component({
    selector: 'my-app',
    template: `
    <hello-world></hello-world>
    <my-counter></my-counter>
`
})
export class AppComponent {}

試してみる

これで何はともあれ表示はされるはず。browserで確認。された。よかよか。

次はformの入れ込みかなあ。じわじわ進めよう。

formの追加?

さてこっからだ。何をどうしたらいいのかさっぱりわからぬ。

でもcomponentの構造上、一番上のcomponentにまずは全部の要素を入れ込んでみればいいと思う。今回はcounter.component.tsか。ここに必要な要素をとりあえずdomで入れ込む。

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

@Component({
    selector: 'my-counter',
    template: `
<div>
 <h2>Counter:0</h2>
 <button>Increment</button>
 <button>Decrement</button>
</div>
`
})
export class CounterComponent {}

こんな感じ。ちゃんと反映されることを確認。

auto build

……しかしそろそろ、手元で変更したら自動でbuildしてほしいなあと思ったりもする。

あ、emacs使っていてmakefileも使ってるならcompile呼び出せるじゃん。M-x compileとM-x recompileでよしとしよう。

いやいやまてまて。なんかあるだろ。……まあいいか。別にこれで困ることもないし。

eventの追加

さてbuttonを追加したのだから次はeventを追加しよう。どうやって。

たぶんbuttonのcomponentを作ってやるんだろうけど。

www.webcreativepark.net

方法EventEmitterなるものがある、と。それでもいけそうだけど初っぱなからapi referenceだけ参照して組むのも怖いのでtutorialとかでそもそもそういうのないのだろうか。

albatrosary.hateblo.jp

あー。これ参考にすればそのまま組めそう。でも公式の説明もみたい。

angular 2 basic counter · GitHub

あ、そのまんまやりたいことをやっているところがあった。ほうほう。export classの中にmethodを入れているのかこれは。で、{{}}で囲った部分には変数を埋め込める、と。

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

@Component({
    selector: 'my-counter',
    template: `
<div>
  <h2>Counter:{{counter}}</h2>
  <button (click)="increment()">Increment</button>
  <button (click)="decrement()">Decrement</button>
</div>
`
})
export class CounterComponent {
    public counter : number = 0;

    increment(){
    this.counter += 1;
    }

    decrement(){
        this.counter -= 1;
    }

}

おーすげえ。できた。何これ早い……。eventもへったくれもなかった……。domとlogicの融合がここまで便利とは思わなかった。びっくりだわ。すげえ。楽。すげえ(やかましい)。

今までだったら頑張ってdivのidを定義して取得して書き換えてとか結構書く必要あっただろうに。

ああそうか。このeventのところでapiたたくとかの機能も入れられるのか。うん。なるほど。楽しくなってきた。

ここまでをgithubにcommit。v0.0.2というtag。

github.com

一応調べておく

今回使ったclick eventの部分のreference。

Angular 2 Events · Learn Angular 2

読んでの通りだった。

次の予定

次はさっきのpageのをまねしてtodo listを入れてみようかな。 ここを参考にして、User Registration and Login Exampleとかもいいかも。

ああそれとそろそろcssやbootstrapも入れ込んでみたい。RxJSも使ってみたいし。

当面の課題はこんなところかなあ。