LoginSignup
1
1

More than 3 years have passed since last update.

Aurelia Todoアプリの作成

Posted at

はじめに

今回やること

今回は、Aureliaフレームワークを使って、Todoアプリの作成を行います。
本記事で扱うTodoアプリのチュートリアルは、Aureliaの公式サイトで提供されているものと同じです。
英語で問題ない方は、下記の公式サイトを見て作成した方が良いです。

Quick Start | Aurelia

aureliaのプロジェクト作成

aurelia-cliを利用

Aureliaのスタンダードなプロジェクトを作成するaurelia-cliを利用します。
aurelia-cli については、下記のページを参照ください。

Basics | Aurelia

コマンド実行順

コマンドの実行順を簡単に記載します。

  1. 下記コマンドで、npmを使用して、 aurelia-cli をインストールします。
    npm install aurelia-cli -g
  2. 下記コマンドを実行すると、プロジェクトを作成できます。
    au new
  3. 作成したプロジェクトに移動します。
    cd <作成したプロジェクト名>
  4. 下記コマンドを実行します。
    au run
  5. http://localhost:8080 にアクセスすると、Hello Aurelia! と表示されます。

事前準備

以降のチュートリアルをスムーズに行うために、
今回作成するTodoアプリには必要のない記述を修正・削除しましょう。
まず、下記ファイルは削除してください。
src/resources/index.ts

次に、下記ファイルを以下のように修正してください。

src/main.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クラス を作成します。
以下のファイルを作成してください。

src/todo.ts
export class Todo {
  done = false;
  constructor(public description: string) { }
}

doneは、そのTodoをやったかどうかを管理するためのプロパティです。
例) タスクA:「醤油を買って帰る」があります。
 醤油を買って帰ると、タスクAのdoneはtrueに変更できます。

descriptionは、タスクの説明です。
上記の例でいうと、「醤油を買って帰る」の部分です。

Appクラスの修正

Appクラスから、以下のように1行削除して保存しましょう。

src/app.ts
export class App {
-  public message: string = 'Hello World!';
}

上記の行を消したため、
ブラウザ( http://localhost:8080 )をみると、Hello World!は表示されなくなっています。
src/app.htmlで表示していたmessageを消してしまったからですね。

それでは、AppクラスにTodoリストの中身と、Todoを操作するメソッドを追加しましょう。

src/app.ts
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フレームワークの設定ファイル

index.ejs
<body aurelia-app="main">
</body>

index.ejsbodyタグは、上記のようになっています。
aurelia-appという属性に渡された"main"は、src/main.tsのことです。
(aurelia-app="src/main" と書いても、同じようにsrc/main.tsを見ます。)

この属性は、Aureliaフレームワークのconfiguration(設定)が、
どのファイルに記載されているのかを示しています。

それでは、src/main.tsを見てみましょう。

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を以下のように変更しましょう。

src/app.html
<template>
-  <h1>${message}</h1>
+  <h1>${heading}</h1>
</template>

これを保存すると、画面にはTodosと表示されているかと思います。
この${heading}は、先ほどsrc/app.tsで定義しましたね。
(ちなみにtemplateタグについてですが、すべてのviewはtemplateタグで囲む必要があります。)

次に、Todoを画面から追加するためのフォームを作ってみましょう。

src/app.html
<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メソッドの中身を振り返ってみましょう。

src/app.ts
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リストを画面に表示しましょう。

src/app.html
<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 todostodoは、配列から取り出したTodoオブジェクトにつけた名前です。

以下の部分を見てください。

<input type="checkbox" checked.bind="todo.done">
<span>
  ${todo.description}
</span>

1つのTodoオブジェクトのdonedescriptionの値がそれぞれ参照されています。
チェックボックスに関しては、checkedに対してdoneの値がバインドされています。
そのため、チェックボックスにチェックを入れると、doneの値がtrueに切り替わります。

「Remove」ボタン

<button click.trigger="removeTodo(todo)">Remove</button>

「Remove」ボタンをクリックすると、removeTodoメソッドが実行されます。
ここで、removeTodoメソッドの中身を振り返ってみましょう。

src/app.ts
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を以下のように変更します。

src/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>

これで、donetrueであれば取り消し線が表示されるようになります。
doneの値は、チェックボックスを変更することで切り替えられます。

以上で、Todoアプリの完成です!

おわりに Aureliaについて

下記は、公式サイトからAureliaのアピールポイントを抜粋した文章です。

Aureliaは、シンプルな方法によってデザインされています。
そのため、たくさんの設定やテンプレートを書く必要がありません。
また、カスタマイズしたり、プラグインを使ったりできるようにデザインされています。
フレームワークを意識せず、プレーンなTypeScriptのみを書くことができます。

おまけ 「Clear All」ボタン

ここまでの内容を参考に、押すとTodoリストがすべてクリアされるボタンを作ってみましょう。
app.tsに下記メソッドを追加して、 app.html 内に、ボタンを追加してみましょう。

src/app.ts
removeTodo(todo: Todo) {
  let index = this.todos.indexOf(todo);
  if (index !== -1) {
    this.todos.splice(index, 1);
  }
}

+  // Todoリストがすべてクリアされるような機能を提供するメソッドの中身を書いてみましょう
+  clearAllTodos() {
+  }
}

1
1
0

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
1
1