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:データクラスのメンバ名)