とりあえず書きなぐる

とりあえず、マイノリティーなプログラムを極力説明せずに書きなぐります

HandsonTableを使ってみるの2

HandsonTable用にサンプルページを用意します
/Views/Table/index.vbhtme
/Controllers/TableController.vb
/Src/table.ts
/Src/app.ts

App.tsにはダミーデータを格納しておきます

サーバーサイド、コントローラーはテンプレのまま
HTMLの発射台機能のみなので大抵これで事足ります

Public Class TableController
    Inherits System.Web.Mvc.Controller

    '
    ' GET: /Table

    Function Index() As ActionResult
        Return View()
    End Function

End Class


基本的にTypeScript側であれやこれややるのでビューもシンプル
ツールバーのボタンとフッターは飾りです

<!DOCTYPE html>
<html>
<head>
  <title>Home</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta charset="utf-8" />

  <link rel="stylesheet" href="@Url.Content("~/Content/jquery.mobile-1.4.5.min.css")" />
  <link rel="stylesheet" href="@Url.Content("~/Content/handsontable/handsontable.full.min.css")" />
  <link rel="stylesheet" href="@Url.Content("~/Src/cm.css")" />
  <link rel="stylesheet" href="@Url.Content("~/Src/app.css")" />

  <script type="text/javascript" src="@Url.Content("~/Scripts/jquery-2.1.3.min.js")"></script>
  <script type="text/javascript" src="@Url.Content("~/Scripts/jquery.mobile-1.4.5.min.js")"></script>
  <script type="text/javascript" src="@Url.Content("~/Scripts/handsontable/handsontable.full.min.js")"></script>
  <script type="text/javascript" src="@Url.Content("~/Src/cm.js")"></script>
  <script type="text/javascript" src="@Url.Content("~/Src/ht.js")"></script>
  <script type="text/javascript" src="@Url.Content("~/Src/app.js")"></script>
  <script type="text/javascript" src="@Url.Content("~/Src/table.js")"></script>

  <style type="text/css">
    div.ui-header > .ui-title {
      border-color: green;
      background-color: green;
      color: white;
    }

    .ui-btn-active {
      border-color: green !important;
      background-color: green !important;
    }
  </style>
</head>
<body class="ui-nodisc-icon ui-alt-icon ui-desktop">
  <div data-role="page" id="page1">

    <div data-role="header" data-position="fixed" data-fullscreen="false" data-tap-toggle="false">
      <h1 class="ui-icon ui-icon-table-w ui-title-left">Table</h1>
      <a href="#" class="ui-btn ui-btn-icon-notext ui-icon-bars ui-btn-right ui-toolbtn"></a>

      <div class="ui-toolbar" id="page1_toolbar1">
        <div class="ui-left-panel">
          <div class="ui-toolbar-divider">
            <a href="#" class="ui-btn ui-btn-icon-left ui-icon-plus">追加</a>
            <a href="#" class="ui-btn ui-btn-icon-left ui-icon-edit">編集</a>
            <a href="#" class="ui-btn ui-btn-icon-left ui-icon-delete">削除</a>
          </div>
          <div class="ui-toolbar-divider">
            <a href="#" class="ui-btn ui-btn-icon-left ui-icon-info">情報</a>
            <a href="#" class="ui-btn ui-btn-icon-left ui-icon-clock">履歴</a>
          </div>
        </div>
        <div class="ui-right-panel">
          <div class="ui-toolbar-divider">
            <a href="#" class="ui-btn ui-btn-icon-notext ui-icon-carat-l"></a>
            <a href="#" class="ui-btn ui-btn-icon-notext ui-icon-carat-r"></a>
            <a href="#" class="ui-btn ui-btn-icon-left ui-icon-search">検索</a>
            <a href="#" class="ui-btn ui-btn-icon-notext ui-icon-bullets"></a>
          </div>
          <div class="ui-toolbar-divider">
            <a href="#" class="ui-btn ui-btn-icon-notext ui-icon-refresh"></a>
            <a href="#" class="ui-btn ui-btn-icon-notext ui-icon-power"></a>
          </div>
        </div>
      </div>
    </div>

    <div role="main" class="ui-content ui-nopadding">
      <div id="list_table"></div>
    </div>

    <div data-role="footer" data-position="fixed" data-fullscreen="false" data-tap-toggle="false">
      <h1>Footer</h1>
    </div>
  </div>
</body>
</html>

ヘッダー、ツールバーボタンの為にアイコン設定を追加します
/Src/app.css

/* 
  Icon 
  From: http://andymatthews.net/code/jQuery-Mobile-Icon-Pack/builder/
*/

....

.ui-icon-table-w:after {
  background-image: url('data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M142.857%20383.929v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM142.857%20276.786v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM285.714%20383.929v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM142.857%20169.643v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM285.714%20276.786v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM428.571%20383.929v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM285.714%20169.643v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM428.571%20276.786v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM428.571%20169.643v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM464.286%2080.357v303.571q0%2018.415-13.114%2031.529t-31.529%2013.114h-375q-18.415%200-31.529-13.114t-13.114-31.529v-303.571q0-18.415%2013.114-31.529t31.529-13.114h375q18.415%200%2031.529%2013.114t13.114%2031.529z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E');
  background-size: 20px;
  border-radius: 0;
}

.ui-icon-table-b:after {
  background-image: url('data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M142.857%20383.929v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM142.857%20276.786v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM285.714%20383.929v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM142.857%20169.643v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM285.714%20276.786v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM428.571%20383.929v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM285.714%20169.643v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM428.571%20276.786v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM428.571%20169.643v-53.571q0-3.906-2.511-6.417t-6.417-2.511h-89.286q-3.906%200-6.417%202.511t-2.511%206.417v53.571q0%203.906%202.511%206.417t6.417%202.511h89.286q3.906%200%206.417-2.511t2.511-6.417zM464.286%2080.357v303.571q0%2018.415-13.114%2031.529t-31.529%2013.114h-375q-18.415%200-31.529-13.114t-13.114-31.529v-303.571q0-18.415%2013.114-31.529t31.529-13.114h375q18.415%200%2031.529%2013.114t13.114%2031.529z%22%20fill%3D%22%23000000%22%20%2F%3E%3C%2Fsvg%3E');
  background-size: 20px;
  border-radius: 0;
}
/* 
  buildin icon 
*/
.ui-icon-alert:after,
.ui-icon-power:after,
.ui-icon-clock:after,
.ui-icon-info:after,

...

}

/Src/App.ts

/// <reference path="../scripts/typings/moment/moment.d.ts"/>
namespace App {
     /*
      * テーブルに表示するデータクラス
      */
    export class TableData {
        data_no = "";
        data_state_cd = 0;
        data_state = "";
        data_date = "";
        data_name = "";
        customer_cd = "";
        customer_name = "";
        handle_cd = "";
        handle_name = "";
        price = 0;
        create_date = "";
        create_user_cd = "";
        create_user = "";
        modify_date = "";
        modify_user_cd = "";
        modify_user = "";
    }

    export function duildTableData(): TableData[] {
        let dts: TableData[] = [];

        for (let i = 0; i < 100; i++) {
            let dt = new TableData;

            dt.data_no = "DNO_" + i.toFillZero(5);
            dt.data_state_cd = i;
            dt.data_state = "State" + i;
            dt.data_date = moment().format("YYYY/MM/DD");
            dt.data_name = "データ名称" + i + "データ名称" + i + "データ名称" + i;
            dt.customer_cd = "Customer" + i;
            dt.customer_name = "顧客名" + i;
            dt.handle_cd = "handle" + i;
            dt.handle_name = "担当者名" + i;
            dt.price = i * 1000;
            dt.create_date = moment().format("YYYY/MM/DD hh:mm:ss");
            dt.create_user_cd = "user" + i;
            dt.create_user = "作成者" + i;
            dt.modify_date = moment().format("YYYY/MM/DD hh:mm:ss");
            dt.modify_user_cd = "user" + i;
            dt.modify_user = "更新者" + i;

            dts.push(dt);
        }
        return dts;
    }
}

/Src/Table.ts

/// <reference path="../scripts/typings/jquery/jquery.d.ts"/>
/// <reference path="../scripts/typings/jquerymobile/jquerymobile.d.ts"/>
/// <reference path="../scripts/typings/handsontable/handsontable.d.ts"/>

namespace Table {
    "use strict";

    namespace mq {
        let mm = window.matchMedia("(min-width:28em) and (min-height:28em)");
        mm.addListener(function (event: MediaQueryList) {
            update();
        });
        export function isMatch(): boolean {
            return mm.matches;
        }
        export function update() {
            if (mm.matches) {
                $(".ui-header .ui-toolbar").resetDisplay();
                $(".ui-header .ui-toolbtn").hide();
            } else {
                $(".ui-header .ui-toolbar").hide();
                $(".ui-header .ui-toolbtn").resetDisplay();
            }
            $(document).trigger("mq_responsive");
        }
    }

    /*
     * 表示前
     */
    $(document).on("pagecontainerbeforeshow", function (event: Event, ui: any) {
        switch (cm.getToPageId(ui)) {
            case "page1":
                cm.hideBodyOverflowY(true);		// 縦スクロールなし
                break;
            default:
                cm.hideBodyOverflowY(false);
        }
    });

    namespace Page1 {
        let _ht: Handsontable = null;				// HandsonTable
        let _resizeDelay = new DelayTimer(500);	// リサイズ遅延タイマー

	/*
	 * ページ表示
	 */
        $(document).on("pagecontainershow", function (event: Event, ui: any) {
            if (cm.getToPageId(ui) !== "page1") {
                return;
            }

            // テーブル設定
            if (!_ht) {
                HTable.build();
            }
            // データ読込
            {
                let dts = App.duildTableData();
                _ht.loadData(dts);
                _ht.updateSettings({ maxRows: dts.length }, false);	// データ数設定
                Ht.setFullSize(_ht);
            }
            _ht.render();			// 再描画
            mq.update();
            $(window).resize();
        });

	/*
	 * リサイズ
	 */
        $(window).on("resize", function (event: Event) {
            if (cm.getActivePageId() !== "page1") {
                return;
            }
            // 一定時間変更がない場合のみテーブルサイズ設定
            _resizeDelay.timeout(function () {
                Ht.setFullSize(_ht);
            });
        });

	/*
	 * テーブル
	 */
        namespace HTable {
	    /*
	     * 作成
	     */
            export function build() {
                _ht = new Handsontable($("#list_table")[0], {
                    data: null
                    , columns: getColumns()					// 列設定
                    , colHeaders: true						// 列見出し
                    , rowHeaders: true						// 行見出し
                    , rowHeaderWidth: 30					// 行見出し幅
                    , manualColumnResize: true				// 列幅変更
                    , multiSelect: false					// 複数選択
                    , stretchH: "none"						// 水平ストレッチ
                    , autoColumnSize: false					// 自動サイズ調整
                    , wordWrap: false						// セル内折り返し
                    , outsideClickDeselects: false			// 選択を維持
                    , disableVisualSelection: "area"		// 範囲選択不可
                    , selectionMode: "single"               // 選択モード
                    , startRows: 0							// データ無時の行数
                    , trimWhitespace: false					// 前後の空白トリム
                    , currentRowClassName: "current-row"	// 選択列にクラス名付加
                    , rowHeights: function (row: number) {	// 行高さ
                        return 50;
                    }
                    , enterMoves: { row: 0, col: 0 }        // Enterキー移動先
                    , autoWrapCol: false					// 列移動ループ
                    , autoWrapRow: false					// 行移動ループ
                    , fillHandle: false                     // 選択範囲の値コピー
                });
                Ht.setFullSize(_ht);	// 全面表示
            }

            /*
             * カラム設定
             */
            function getColumns(): Object[] {
                return [
                    {
                        type: "text"
                        , title: "番号"
                        , data: "data_no"
                        , readOnly: true
                        , colWidths: 100
                    }
                    , {
                        type: "text"
                        , title: "状態"
                        , data: "data_state"
                        , readOnly: true
                        , colWidths: 100
                    }
                    , {
                        type: "text"
                        , title: "日付"
                        , data: "data_date"
                        , readOnly: true
                        , colWidths: 100
                    }
                    , {
                        type: "text"
                        , title: "名称"
                        , data: "data_name"
                        , readOnly: true
                        , colWidths: 300
                    }
                    , {
                        type: "text"
                        , title: "顧客名"
                        , data: "customer_name"
                        , readOnly: true
                        , colWidths: 100
                    }
                    , {
                        type: "text"
                        , title: "担当者"
                        , data: "handle_name"
                        , readOnly: true
                        , colWidths: 100
                    }
                    , {
                        type: "numeric"
                        , title: "金額"
                        , data: "price"
                        , numericFormat: {
                            pattern: "0,000,"
                            , culture: "ja-JP"
                        }
                        , readOnly: true
                        , colWidths: 100
                    }
                    , {
                        type: "text"
                        , title: "作成日"
                        , data: "create_date"
                        , readOnly: true
                        , colWidths: 150
                    }
                    , {
                        type: "text"
                        , title: "作成者"
                        , data: "create_user"
                        , readOnly: true
                        , colWidths: 100
                    }
                    , {
                        type: "text"
                        , title: "更新日"
                        , data: "modify_date"
                        , readOnly: true
                        , colWidths: 150
                    }
                    , {
                        type: "text"
                        , title: "更新者"
                        , data: "modify_user"
                        , readOnly: true
                        , colWidths: 100
                    }
                ];
            }
        }
    }

データはJSON形式でも可能ですが、どこまでいってもanyなのでデータクラスを作成しておきます
テーブル作成オプションはお好みですが、固定行/列の設定はクライアントスペックにかなり依存します
カラム設定時にクラスメンバとバインドします(data:データクラスのメンバ名)