はじめに
今回やること
今回は、Aureliaフレームワークを使って、Todoアプリの作成を行います。
本記事で扱うTodoアプリのチュートリアルは、Aureliaの公式サイトで提供されているものと同じです。
英語で問題ない方は、下記の公式サイトを見て作成した方が良いです。
aureliaのプロジェクト作成
aurelia-cliを利用
Aureliaのスタンダードなプロジェクトを作成するaurelia-cli
を利用します。
aurelia-cli
については、下記のページを参照ください。
コマンド実行順
コマンドの実行順を簡単に記載します。
- 下記コマンドで、npmを使用して、
aurelia-cli
をインストールします。
npm install aurelia-cli -g
- 下記コマンドを実行すると、プロジェクトを作成できます。
au new
- 作成したプロジェクトに移動します。
cd <作成したプロジェクト名>
- 下記コマンドを実行します。
au run
-
http://localhost:8080 にアクセスすると、
Hello Aurelia!
と表示されます。
事前準備
以降のチュートリアルをスムーズに行うために、
今回作成するTodoアプリには必要のない記述を修正・削除しましょう。
まず、下記ファイルは削除してください。
src/resources/index.ts
次に、下記ファイルを以下のように修正してください。
import {Aurelia} from 'aurelia-framework'
-import environment from './environment';
import {PLATFORM} from 'aurelia-pal';
export function configure(aurelia: Aurelia) {
- aurelia.use
- .standardConfiguration()
- .feature(PLATFORM.moduleName('resources/index'));
-
- aurelia.use.developmentLogging(environment.debug ? 'debug' : 'warn');
-
- if (environment.testing) {
- aurelia.use.plugin(PLATFORM.moduleName('aurelia-testing'));
- }
-
+ aurelia.use.basicConfiguration();
aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName('app')));
}
Chapter1 TodoクラスとAppクラスの作成
Todoクラスの追加
まず、一つ一つのTodoを表すオブジェクトのための Todoクラス
を作成します。
以下のファイルを作成してください。
export class Todo {
done = false;
constructor(public description: string) { }
}
done
は、そのTodoをやったかどうかを管理するためのプロパティです。
例) タスクA:「醤油を買って帰る」があります。
醤油を買って帰ると、タスクAのdoneはtrueに変更できます。
description
は、タスクの説明です。
上記の例でいうと、「醤油を買って帰る」の部分です。
Appクラスの修正
Appクラスから、以下のように1行削除して保存しましょう。
export class App {
- public message: string = 'Hello World!';
}
上記の行を消したため、
ブラウザ( http://localhost:8080 )をみると、Hello World!
は表示されなくなっています。
src/app.html
で表示していたmessage
を消してしまったからですね。
それでは、AppクラスにTodoリストの中身と、Todoを操作するメソッドを追加しましょう。
import {Todo} from './todo';
export class App {
heading = "Todos";
todos: Todo[] = [];
todoDescription = '';
addTodo() {
if (this.todoDescription) {
this.todos.push(new Todo(this.todoDescription));
this.todoDescription = '';
}
}
removeTodo(todo) {
let index = this.todos.indexOf(todo);
if (index !== -1) {
this.todos.splice(index, 1);
}
}
}
上から順番に説明していきましょう。
import {Todo} from './todo';
このコードは、 src/todo.ts
から、Todoクラスをインポートしています。
heading = "Todos";
todos: Todo[] = [];
todoDescription = '';
heading
は画面に表示するタイトルです。"Todos"
の部分は好きな言葉にしてもらって問題ありません。
todos
は、画面に表示するTodoリストです。Todoクラスのオブジェクトの配列になっています。
todoDescription
は、画面で入力するそれぞれのTodoの説明です。(「醤油を買って帰る」のことです。)
次に、各メソッドを紹介します。
addTodo
メソッドは、todos
の配列に新しいTodoを追加するための関数です。
removeTodo
メソッドは、選択したTodoをTodoリストから削除するための関数です。
それぞれのメソッドについての細かい説明は、また後ほどします。
ここまでで注目すべき点は、我々はまだTypeScriptのソースしか書いていないということです。
次のチャプターでは、作成したAppクラスの内容を画面に表示してみます。
Chapter2 画面のレンダリング
それでは、画面のレンダリングをしましょう。
しかし、お気づきだとは思うのですが、画面のレンダリングはすでに行われています。
(最初にau run
した時に、すでに画面にはHello World!
が表示されていましたよね。)
それでは、どのようにして画面のレンダリングが行われているのかを確認しましょう。
Aureliaフレームワークの設定ファイル
<body aurelia-app="main">
</body>
index.ejs
のbody
タグは、上記のようになっています。
aurelia-app
という属性に渡された"main"
は、src/main.ts
のことです。
(aurelia-app="src/main"
と書いても、同じようにsrc/main.ts
を見ます。)
この属性は、Aureliaフレームワークのconfiguration(設定)が、
どのファイルに記載されているのかを示しています。
それでは、src/main.ts
を見てみましょう。
import {Aurelia} from 'aurelia-framework'
import {PLATFORM} from 'aurelia-pal';
export function configure(aurelia: Aurelia) {
aurelia.use.basicConfiguration();
aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName('app')));
}
これが、Aureliaフレームワークにおけるメインファイルです。
メインファイルでconfigure
メソッドをエクスポートすることで、Aureliaの設定ができます。
Aureliaフレームワークは、Aureliaオブジェクトのインスタンスを作成します。
そして、そのAureliaオブジェクトに対して使用できる、様々な設定やプラグイン、拡張などがあります。
上記のファイルの内容を簡単に説明します。
aurelia.use.basicConfiguration();
上記の部分は、基本的なconfigurationを設定するメソッドを実行しています。
aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName('app')));
aurelia.start()
は、必要なプラグインやリソースを読み込んで、Aureliaのインスタンスを開始します。
aurelia.setRoot
ですが、ルートになるコンポーネントを指定しています。
ここでは、./app.ts
を指定しています。
Todoリストの表示
Todo追加フォームの表示
さて、それでは、app.htmlを以下のように変更しましょう。
<template>
- <h1>${message}</h1>
+ <h1>${heading}</h1>
</template>
これを保存すると、画面にはTodos
と表示されているかと思います。
この${heading}
は、先ほどsrc/app.ts
で定義しましたね。
(ちなみにtemplate
タグについてですが、すべてのviewはtemplate
タグで囲む必要があります。)
次に、Todoを画面から追加するためのフォームを作ってみましょう。
<template>
<h1>${heading}</h1>
+
+ <form submit.trigger="addTodo()">
+ <input type="text" value.bind="todoDescription">
+ <button type="submit">Add Todo</button>
+ </form>
</template>
これで画面にフォームが表示されたかと思います。
Todoの入力
<input type="text" value.bind="todoDescription">
value
属性に.bind
を追加することで、
app.html
に対応するビューモデル(app.ts
のこと)に"todoDescription"
をバインドすることができます。
Aureliaでは、.bind
を追加するだけで、どのようなHTMLの属性もバインドすることができます。
(この.bind
は、双方向のバインディングです。バインド用のコマンドは、他にもあります。
例: .one-way
.two-way
.one-time
)
「Add Todo」ボタン
<form submit.trigger="addTodo()">
ここではsubmit
というDOMイベントに.trigger
を追加しています。
submit
イベントが起きるとaddTodo
メソッドが実行されるようになっています。
Aureliaでは、あらゆるDOMイベントをキャッチして、.trigger
を追加することができます。
ここで、addTodo
メソッドの中身を振り返ってみましょう。
addTodo() {
if (this.todoDescription) {
this.todos.push(new Todo(this.todoDescription));
this.todoDescription = '';
}
}
addTodo
メソッドでは、todoDescriptionが入力されている場合、
入力値をdescription
に持つ新しいTodoオブジェクトを作成します。
作成したTodoオブジェクトをtodos
(Todoの配列)に追加します。
そして、入力値(value
)をクリアします。
こうして、入力した値からTodoリストがどんどん作成されます。
Todoリストの表示
今のままではTodoが本当に追加されているのかが分かりません。
次は、作成したTodoリストを画面に表示しましょう。
<template>
<h1>${heading}</h1>
<form submit.trigger="addTodo()">
<input type="text" value.bind="todoDescription">
<button type="submit">Add Todo</button>
</form>
+
+ <ul>
+ <li repeat.for="todo of todos">
+ <input type="checkbox" checked.bind="todo.done">
+ <span>
+ ${todo.description}
+ </span>
+ <button click.trigger="removeTodo(todo)">Remove</button>
+ </li>
+ </ul>
</template>
ブラウザを確認してみましょう。
入力して「Add Todo」ボタンを押すと、フォームの下にどんどんリストが追加されるはずです。
Todoリストのループ
<li repeat.for="todo of todos">
このシンタックスは、for...of
のループから出来ています。
todos
の配列から要素の数だけli
タグとその中身を生成しているのです。
todo of todos
のtodo
は、配列から取り出したTodoオブジェクトにつけた名前です。
以下の部分を見てください。
<input type="checkbox" checked.bind="todo.done">
<span>
${todo.description}
</span>
1つのTodoオブジェクトのdone
とdescription
の値がそれぞれ参照されています。
チェックボックスに関しては、checked
に対してdone
の値がバインドされています。
そのため、チェックボックスにチェックを入れると、done
の値がtrue
に切り替わります。
「Remove」ボタン
<button click.trigger="removeTodo(todo)">Remove</button>
「Remove」ボタンをクリックすると、removeTodo
メソッドが実行されます。
ここで、removeTodo
メソッドの中身を振り返ってみましょう。
removeTodo(todo: Todo) {
let index = this.todos.indexOf(todo);
if (index !== -1) {
this.todos.splice(index, 1);
}
}
removeTodo
メソッドでは、
todosの配列の中から、削除する対象のTodoオブジェクトのindexを探し、
todosからそのindexの要素を取り除きます。
そのため、 「Remove」ボタンを押すと、そのTodoは削除されます。
doneチェックボックス
doneチェックボックスの変化がわかりづらいので、
doneの状態によってCSSを変化させてみましょう。
app.html
を以下のように変更します。
<ul>
<li repeat.for="todo of todos">
<input type="checkbox" checked.bind="todo.done">
- <span>
+ <span css="text-decoration: ${todo.done ? 'line-through' : 'none'}">
${todo.description}
</span>
<button click.trigger="removeTodo(todo)">Remove</button>
</li>
</ul>
これで、done
がtrue
であれば取り消し線が表示されるようになります。
done
の値は、チェックボックスを変更することで切り替えられます。
以上で、Todoアプリの完成です!
おわりに Aureliaについて
下記は、公式サイトからAureliaのアピールポイントを抜粋した文章です。
Aureliaは、シンプルな方法によってデザインされています。
そのため、たくさんの設定やテンプレートを書く必要がありません。
また、カスタマイズしたり、プラグインを使ったりできるようにデザインされています。
フレームワークを意識せず、プレーンなTypeScriptのみを書くことができます。
おまけ 「Clear All」ボタン
ここまでの内容を参考に、押すとTodoリストがすべてクリアされるボタンを作ってみましょう。
app.ts
に下記メソッドを追加して、 app.html
内に、ボタンを追加してみましょう。
removeTodo(todo: Todo) {
let index = this.todos.indexOf(todo);
if (index !== -1) {
this.todos.splice(index, 1);
}
}
+ // Todoリストがすべてクリアされるような機能を提供するメソッドの中身を書いてみましょう
+ clearAllTodos() {
+ }
}