08.todoアプリ コントローラの作成
本章ではコントローラを作成します。ビューに定義したボタンやテーブル、フォーム要素の操作によって行われる処理を実装します。
コントローラでは前章で作成したロジックを使用して、データを登録や更新、削除を行います。
このページで説明するコードは、サンプルコードのtodoController.jsに記述されています。
コントローラの構成
コントローラToDoControllerに、以下の処理を実装します。
TODO登録フォーム
- 登録ボタンが押されたら、TODOテキストボックスに入力された値をデータモデルに登録する。
- TODOテキストボックスでエンターが押されたら、TODOテキストボックスに入力された値をデータモデルに登録する。
TODO一覧
- テーブルの行がクリックされたら、テーブルの下にTODOの詳細を表示する。
- ステータスのチェックボックスが操作されたら、操作に応じてToDoModelのstatusを更新する。
- ステータスのチェックボックスがチェックされたら、TODO内容に打ち消し線をつける。
TODO詳細
- 削除ボタン押されたら、現在詳細に表示しているデータアイテムをToDoModelから削除し、画面を更新する。
- 更新ボタンが押されたら、フォームで入力された値でデータアイテムを更新する。
また、__readyのライフサイクルイベントで、ToDoLogic#init()を実行してTODOデータを取得し、コメントビューにそのデータをバインドします。
サンプルコード
ToDoControllerのコードは以下のとおりです。
__name: 'sample.todo.controller.TodoController',
todoLogic: sample.todo.logic.TodoLogic,
/**
* TODOリストのデータをサーバから取得し画面に表示します。
* <p>
* ※今回はJSONファイルからサンプルデータを取得しています。
*/
__ready: function() {
var that = this;
this.todoLogic.init().done(function(data) {
that.view.bind('h5view#tmplTodos', {
todos: data
});
});
},
/**
* 登録ボタンが押下されたときの処理
* <p>
* テキストに入力されたTODOの内容をデータモデルに登録します。
*
* @param {Object} context イベントコンテキスト
*/
'#btnRegist click': function(context) {
this._insertToDo(context);
},
/**
* TODOのテキストボックスでエンターキーが押下されたときの処理
* <p>
* テキストに入力されたTODOの内容をデータモデルに登録します。
*
* @param {Object} context イベントコンテキスト
*/
'#todoRegForm submit': function(context) {
this._insertToDo(context);
},
/**
* TODOリスト一覧のチェックボックスが操作されたときの処理
* <p>
* チェックまたは未チェックによって、データアイテムのステータスを更新します。
*
* @param {Object} context イベントコンテキスト
*/
'#list tbody input[type="checkbox"] click': function(context) {
var target = context.event.currentTarget;
var id = this._getSelectedItemId($(target).closest('tr'));
var status = target.checked;
this.todoLogic.update(id, {
status: status
});
context.event.stopPropagation();
},
/**
* 選択された行のTODO情報の詳細を表示します。
*
* @param {Object} context イベントコンテキスト
*/
'#list tbody tr click': function(context) {
var that = this;
var id = this._getSelectedItemId(context.event.currentTarget);
var detail = this.todoLogic.getDetail(id);
if ($('#detailForm').children().length === 0) {
this.view.bind('h5view#tmplDetail', {
detail: detail
});
}
// 詳細画面に移動する
setTimeout(function() {
window.scrollTo(0, that.$find('#detailForm').offset().top);
}, 100);
},
/**
*
* 詳細画面のテキストボックスでエンターキーが押下されたときの処理
* <p>
* submitが動作しないようイベントをキャンセルします。
*
* @param {Object} context イベントコンテキスト
*/
'#detailForm submit': function(context) {
// formのsubmitが動作しないようイベントをキャンセルする
context.event.preventDefault();
},
/**
* 削除ボタンが押下されたときの処理
* <p>
* 詳細画面に表示されているTODOデータを削除します。
*
* @param {Object} context イベントコンテキスト
*/
'#btnDel click': function(context) {
var params = this._getFormData();
this.todoLogic.remove(parseInt(params.id));
// formのsubmitが動作しないよう伝播を止める
context.event.stopPropagation();
// ページの先頭に移動する
h5.ui.scrollToTop();
},
/**
* 更新ボタンが押下されたときの処理
* <p>
* 詳細画面に入力された情報でTODOデータを更新します。
*
* @param {Object} context イベントコンテキスト
*/
'#btnUpdate click': function(context) {
var params = this._getFormData();
this.todoLogic.update(params.id, {
content: params.content,
status: !!params.status
});
// formのsubmitが動作しないよう伝播を止める
context.event.stopPropagation();
// ページの先頭に移動する
h5.ui.scrollToTop();
},
/**
* TODOデータの登録処理を行います。
*
* @param {Object} ctx イベントコンテキスト
*/
_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();
},
/**
* 一覧で選択された行のアイテムIDを取得します。
*
* @param targetElem {DOMElement} イベント発生要素
* @returns アイテムID
*/
_getSelectedItemId: function(targetElem) {
return $(targetElem).find('input[data-h5-bind="id"]').val();
},
/**
* 詳細画面の入力値を取得します。
*
* @returns {Object} 入力値が格納されたオブジェクト
*/
_getFormData: function() {
var param = {};
$.each(this.$find('#detailForm').serializeArray(), function(i, obj) {
param[obj.name] = obj.value;
});
return param;
}
};
// sample.todo.controller.ToDoControllerでグローバルに公開する
h5.core.expose(todoController);
sample.todo.controller.ToDoControllerに公開したコントローラを、h5.core.controller()でDOM要素にバインドします。
サンプルコードを実行する(コントローラのバインド)
以上で、データモデル、ビュー、ロジック、コントローラを作成は全て完了しました。
あとは、以下のコードを実行して、コントローラをDOM要素にバインドしTODO管理アプリを実行して下さい。
以上でサンプルアプリの作成は終了です。データモデルを使用すると、型のないJavaScriptにおいて、データ整合性や仕様変更時の意図しない代入を防ぐことができます。また、データバインドを使用すると、基本的なデータ操作を行う場面で、データの表示・反映を簡単に行うことができます。ぜひこれらの機能を活用してみてください!