開発者ブログ
チュートリアル(データバインド編) » 08.todoアプリ コントローラの作成

08.todoアプリ コントローラの作成

Last modified by masaru-yokoyama on 2013/07/11, 21:13

本章ではコントローラを作成します。ビューに定義したボタンやテーブル、フォーム要素の操作によって行われる処理を実装します。
コントローラでは前章で作成したロジックを使用して、データを登録や更新、削除を行います。

このページで説明するコードは、サンプルコードのtodoController.jsに記述されています。

コントローラの構成

コントローラToDoControllerに、以下の処理を実装します。

TODO登録フォーム

  • 登録ボタンが押されたら、TODOテキストボックスに入力された値をデータモデルに登録する。
  • TODOテキストボックスでエンターが押されたら、TODOテキストボックスに入力された値をデータモデルに登録する。

TODO一覧

  • テーブルの行がクリックされたら、テーブルの下にTODOの詳細を表示する。
  • ステータスのチェックボックスが操作されたら、操作に応じてToDoModelのstatusを更新する。
  • ステータスのチェックボックスがチェックされたら、TODO内容に打ち消し線をつける。

TODO詳細

  • 削除ボタン押されたら、現在詳細に表示しているデータアイテムをToDoModelから削除し、画面を更新する。
  • 更新ボタンが押されたら、フォームで入力された値でデータアイテムを更新する。

また、__readyのライフサイクルイベントで、ToDoLogic#init()を実行してTODOデータを取得し、コメントビューにそのデータをバインドします。

サンプルコード

ToDoControllerのコードは以下のとおりです。

var 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管理アプリを実行して下さい。

h5.core.controller('#content', sample.todo.controller.TodoController);

以上でサンプルアプリの作成は終了です。データモデルを使用すると、型のないJavaScriptにおいて、データ整合性や仕様変更時の意図しない代入を防ぐことができます。また、データバインドを使用すると、基本的なデータ操作を行う場面で、データの表示・反映を簡単に行うことができます。ぜひこれらの機能を活用してみてください!


Copyright (C) 2012-2017 NS Solutions Corporation, All Rights Reserved.