hifiveの基本、データモデル/バインドを理解する(2)
前回に続いてデータモデル、バインドの説明を行っていきます。初期データの表示が終わりましたので、続いてTodoの登録と、チェックボックスを付けた時のイベントを説明します。なおソースコードはGitHubにアップしてありますので参考にしてください(todo.html)。実際に動いているデモはこちらになります。
Todoを登録する
Todoを登録するということは、
- データの入力
- 登録ボタンのクリック
- Todoモデルを新規作成
- 入力テキストを消す
- 表示(Todo一覧)を更新
といった順番でフローを行っていくということです。
データの入力

データの入力はテキストボックスに行います。これはHTML(todo.html)に記述があります。
<form id="todoRegForm">
<div class="todo-form corner-all box">
<div class="todo-form-right">
<input type="button" id="btnRegist" class="corner-all ui-button gray" value="登録" tabindex="2">
</div>
<div class="todo-form-left">
<input type="text" id="txtTodo" class="corner-all ui-text txt-todo" placeholder="TODO" tabindex="1">
</div>
</div>
</form>
登録ボタンのクリック

そして処理をハンドリングしているのは javascripts/controller/todoController.js
になります。
'#btnRegist click': function(context) {
this._insertToDo(context);
},
この部分で #btnRegist がクリックされるのを監視しています。クリックされると呼ばれるのは _insertToDoです。同様にTodoのテキストボックスでリターンキーが押された場合(フォームがサブミットされた場合)も処理しておきます。
'#todoRegForm submit': function(context) {
this._insertToDo(context);
},
このようにイベントハンドリングを使うことで同じ処理の使い回しが簡単にできるようになります。
_insertToDo: function(ctx) {
var $txtTodo = this.$find('#txtTodo');
if ($txtTodo.val() === '') {
alert('TODOを入力して下さい。');
} else {
this.todoLogic.add($txtTodo.val());
$txtTodo.val('');
}
// formのsubmitが動作しないよう伝播を止める
ctx.event.preventDefault();
},
この処理の中では簡易的な入力チェックと、todoLogicへの追加だけを行っています。ビュー周りの処理は行っていません。
Todoモデルを新規作成
ではその todoLogic.add を見てみましょう。
add: function(content) {
var item = this.model.create({
id: this._getNewId(),
status: false,
content: content,
insertDate: +new Date()
});
this.todos.push(item);
},
ロジックに紐づくモデル(Todoモデル)の作成をして、それを this.todos に追加しています。
表示(Todo一覧)を更新
上述の通り、ロジックでもやはりビュー周りの処理は行っていません(ロジックはビューと切り離すべきなので当然ですが)。
では実際に表示処理をどこで行っているかというと、元々コントローラを初期化した時点で次のように記述しています。
todoLogic: sample.todo.logic.TodoLogic,
:
__ready: function() {
var that = this;
this.todoLogic.init().done(function(data) {
that.view.bind('h5view#tmplTodos', {
todos: data
});
});
},
ロジックが関連づいているため、ロジックに紐づくモデルへのデータ追加によって h5view#tmplTodos の表示が自動で更新される仕組みになります。さらにこの処理はロジック中の、
todos: h5.core.data.createObservableArray(),
によって todos を監視対象と指定することで実現しています。一覧系のデータ変更に対してビューの処理を必要としないのはとても楽ですね。
Todoを完了する

では次にTodoのチェックボックスを入れた時の処理を見ていきます。HTMLでは次のようになっています。
<tbody data-h5-loop-context="todos">
<tr>
<td class="status">
<input type="hidden" data-h5-bind="id" />
<input type="checkbox" class="ui-check" data-h5-bind="attr(checked):checked"/>
</td>
<td class="content">
<span data-h5-bind="content;style(text-decoration):contentStyle"></span>
</td>
</tr>
</tbody>
そしてこのチェックボックスのクリックイベントを監視しているのが todoController.js になります。
'#list tbody input[type="checkbox"] click': function(context) {
var target = context.event.currentTarget;
var id = this._getSelectedItemId($(target).closest('tr'));
var checked = target.checked;
this.todoLogic.update(id, {
status: checked
});
context.event.stopPropagation();
},
この行で発生したイベントかは context.event.currentTarget で取得ができます(ここではチェックボックスが取得されています)。
_getSelectedItemId というのは選択されている行のidを取得するメソッドです。$(target).closest(‘tr’) を引数で渡している通り、チェックボックスの親要素にあたるtr要素を渡しています。
_getSelectedItemId: function(targetElem) {
return $(targetElem).find('input[data-h5-bind="id"]').val();
},
そして実際のデータ更新処理は this.todoLogic.update にて行っています。
update: function(id, data) {
var item = this.model.get(id);
item.set(data);
},
updateはidを使って該当するデータを取り出して ハッシュで渡されている data に基づいてデータ更新を行っています。なぜ this.model.get(id) でデータが取得できるかというと、todoModel.js で次のように初期化をしているからです。
var todoModel = todoManager.createModel({
name: 'TodoModel',
schema: {
// ID
id: {
id: true,
type: 'integer'
},
:
JSONの要素idに対してid(アイデンティティとしてのid)を true にすることでデータ取得ができるようになります。
この場合においても表示処理は一切行っていません。データの更新をすれば自動的に表示が切り替わるようになっています。
例えばこちらのWebデモにおいて、

sample.todo.controller.TodoController.todoLogic.model.get(1).set({content: "Test"})
とJavaScriptコンソールで実行すると、一番上のタスクの内容がTestに変わるのが確認できるはずです。コントローラ、ロジック、モデルが連携しているからこそ、このような動きが可能になっています。

では次回は最後にTodo詳細の表示と細かな情報修正について紹介します。
コメントは受け付けていません。