MeteorのTutorialを試してみる（３

https://www.meteor.com/try/5
[前回](http://qiita.com/kazusa-qooq/items/f4e9bb6cf5f3681d63b0)に引き続き、MeteorのTutorialに挑戦していきます。
チェック機能とフィルタ機能を追加していきます。MongoDBの練習にもちょうどいい題材かもしれません。

#Checking off and deleting tasks
ToDoアプリならチェックと削除機能が必要だよねということで追加していきます。
内容的にはDBの更新と削除方法を学びます。

まずtaskテンプレートを次のように変更します。

``` simple-todos.html
・・・
<template name="task">
  <li class="{{#if checked}}checked{{/if}}">
    <button class="delete">&times;</button>

    <input type="checkbox" checked="{{checked}}" class="toggle-checked" />

    <span class="text">{{text}}</span>
  </li>
</template>
```
するとチェックボックスと削除ボタンがつきます。
![image](https://qiita-image-store.s3.amazonaws.com/0/71988/c090633d-e939-fe68-8a21-8131545a683f.png)

ただし、まだ見た目だけです。実際に機能させるために、simple-todos.jsに以下を追加します。
追加位置は`if (Meteor.isClient) {}`の中です。

``` simple-todos.js
・・・
  Template.task.events({
    "click .toggle-checked": function () {
      // Set the checked property to the opposite of its current value
      Tasks.update(this._id, {$set: {checked: ! this.checked}});
    },
    "click .delete": function () {
      Tasks.remove(this._id);
    }
  });
・・・
```

`Template.task.events`内でthisはtaskドキュメントになります。それさえわかればあとは見てのとおりです。this._idでドキュメントを指定し、updateとdeleteを行っています。

##Using object properties or helpers to add/remove classes
１点、`<li class="{{#if checked}}checked{{/if}}">`について。これはtask.checkedが真の場合にliにclass="checked"を設定します。これによりCSSを用い、チェックされたタスクのテキストに削除線を引いています。

#Deploying your app
https://www.meteor.com/try/6
Meteorのデプロイ方法です。Cloud9上でやってきたため飛ばしますが、コマンド１つでできるようです。

#Running your app on Android or iOS
https://www.meteor.com/try/7
Cloud9上でやってたため試せませんが、Android・iOSのアプリケーションとしても動くようです。あとMacがないとiOSは試せません。開発機が欲しくなりますね・・・

#Storing temporary UI state in Session
さて、未完了のタスクを確認するためにフィルター機能をアプリに追加します。内容的にはセッションの使い方を学びます。

まずフィルタのON/OFF用のチェックボックスを追加します。`<h1>Todo List</h1>`の直下に以下を記載してください。

```
・・・
      <h1>Todo List</h1>
        <label class="hide-completed">
          <input type="checkbox" checked="{{hideCompleted}}" />
          Hide Completed Tasks
        </label>
・・・
```
画面はこんな感じになります。
![image](https://qiita-image-store.s3.amazonaws.com/0/71988/6458a0fe-2a41-b376-1485-965564823b58.png)

例によってまだ見た目だけです。このチェック状態をセッションに記録し、セッションの状態によってフィルタした結果を得るか、全て取得するか分岐させます。
まずはセッションへの記録です。Template.body.events内に以下を追記します。

``` simple-todos.js
・・・
  Template.body.events({
・・・
　　},
    "change .hide-completed input": function (event) {
      Session.set("hideCompleted", event.target.checked);
    }
    
  });
・・・
```
まんまですね。チェックボックスのchecked状態をセッションにhideCompletedという名前で記録しています。追記するときに , を付け忘れることだけ注意しましょう。

つぎにデータの取得側です。

```
  Template.body.helpers({
    tasks: function () {
      if (Session.get("hideCompleted")) {
        // If hide completed is checked, filter tasks
        return Tasks.find({checked: {$ne: true}}, {sort: {createdAt: -1}});
      } else {
        // Otherwise, return all of the tasks
        return Tasks.find({}, {sort: {createdAt: -1}});
      }
    }
  });
```
こっちもまんまですね。$neはnot equalの略です。checkedフィールドがtrueでないものだけを検索しています。

##Session is a reactive data store for the client
コレクションと異なり、セッションはUIごとに保持され、ブラウザ間で同期されません。試しに２つウィンドウを開いて、リストへの追加は同期されるがフィルタリングは同期されないことを確認するとよいでしょう。

##One more feature: Showing a count of incomplete tasks
フィルタリングの仕方を覚えたついでに残りTodoのカウント機能をつけましょう。
Template.body.helpersに次のヘルパを追加してください。

``` simple-todos.js
    },
    incompleteCount: function () {
      return Tasks.find({checked: {$ne: true}}).count();
    }
```

このヘルパを使って画面に表示します。

``` simple-todos.html
・・・
<h1>Todo List ({{incompleteCount}})</h1>
・・・
```

出来上がりです。
![image](https://qiita-image-store.s3.amazonaws.com/0/71988/2447902c-c942-1e31-f5de-b395a3ef0081.png)

切りがいいので一端きります。
[次回](http://qiita.com/kazusa-qooq/items/c659070ad99f180b4ec8)