Wijmoとのデータ連携

ここでは、InputManJSの入力コントロールとWijmoのグリッドを連携させるときの手順を紹介します。

InputManJSのコントロールは、Wijmoのデータレイヤー機能であるCollectionViewと連携して、様々なデータ連携機能を提供することができます。 データ連結 CollectionViewはJavaScript配列オブジェクトから生成されます。サーバーから取得したJSONデータや、クライアントで生成したデータ配列とのデータ連結に対応します。 InputManJSのコントロールをCollectionViewと連結するには、現在のレコードが変更されたときにコントロールのsetValue(テキストコントロールはsetText)メソッドを実行して、コントロールの値を更新します。 また、InputManJSのコントロールで変更した値をCollectionViewに反映するには、コントロールのgetValue(テキストコントロールはgetText)メソッドで値を取得して、現在のレコードに設定します。 変更データの追跡 CollectionViewは、編集/追加/削除された項目を自動的に追跡して管理します。変更された項目は配列オブジェクトとして取得され、変更データを簡単にサーバーに送信することができます。 現在の項目 CollectionViewでは、配列のインデックスを指定して項目を参照するのではなく、currentItemプロパティで現在の項目を参照します。現在の項目を前/後/先頭/最後に移動するためのメソッドも提供されます。 後述のソートやフィルタリングを適用した場合でも、特別な処理を実装することなく、簡単に現在の項目を移動することができます。 また、CollectionViewを複数のコントロールと連結した場合に、すべてのコントロールで現在の項目の位置が同期されます。このサンプルでは、右上のグリッドコントロールでセルを選択すると、InputManJSのコントロールに選択された行のデータが表示されます。 データビュー グループ化、並べ替え、フィルター、ページングされたデータを取得するためのビューを作成することができます。 これらのビューを作成すると、表示上のデータの順番やデータの有無が変更されますが、連結した元のデータは変更されません。 このサンプルでは、右上のグリッドコントロールで次の操作を行うことができます。 並べ替え:列ヘッダをクリックします。 フィルター:列ヘッダの右側のアイコンをクリックして、リストから表示する値を選択したり、表示する値の条件を指定します。 Wijmoコントロールとの連携 ドロップダウンプラグインを使用すると、Wijmoのコントロールをドロップダウン表示することができます。詳細は「ドロップダウンプラグイン」を参照してください。
import '@mescius/inputman/CSS/gc.inputman-js.css'; import '@mescius/wijmo.styles/wijmo.css'; import './styles.css'; import './license'; import { InputMan } from '@mescius/inputman'; import { FlexGrid } from '@mescius/wijmo.grid'; import { CollectionView } from '@mescius/wijmo'; import { getProducts, categoryNames } from './data'; InputMan.appearanceStyle = InputMan.AppearanceStyle.Modern; const cv = new CollectionView(getProducts(), { trackChanges: true, currentChanged: () => update() }); const grid = new FlexGrid('#grid', { itemsSource: cv, isReadOnly: true, columns: [ { header: '商品コード', binding: '商品コード', width: 100 }, { header: '商品名', binding: '商品名', width: 200 }, { header: '分類', binding: '分類', width: 120 }, { header: '価格', binding: '価格', format: 'c', width: 80 }, { header: '発売日', binding: '発売日', width: 120 } ] }); const gridEdited = new FlexGrid('#gridEdited', { itemsSource: cv.itemsEdited, isReadOnly: true }); const gridAdded = new FlexGrid('#gridAdded', { itemsSource: cv.itemsAdded, isReadOnly: true }); const gridRemoved = new FlexGrid('#gridRemoved', { itemsSource: cv.itemsRemoved, isReadOnly: true }); const controls = { 商品コード: new InputMan.GcMask(document.getElementById('商品コード'), { formatPattern: '\\A\\D{3}' }), 商品名: new InputMan.GcTextBox(document.getElementById('商品名')), 分類: new InputMan.GcComboBox(document.getElementById('分類'), { items: categoryNames }), 価格: new InputMan.GcNumber(document.getElementById('価格'), { displayPositivePrefix: '$', displayNegativePrefix: '-$', displayFormatDigit: '##,##0', showNumericPad: true }), 発売日: new InputMan.GcDateTime(document.getElementById('発売日'), { formatPattern: 'yyy/M/d', displayFormatPattern: '', showDropDownButton: true, dropDownConfig: { dropDownType: InputMan.DateDropDownType.Calendar } }) }; const update = () => { for (var fieldName in controls) { if (fieldName == '商品名') { controls[fieldName].setText(cv.currentItem[fieldName]); } else if (fieldName == '分類') { controls[fieldName].setSelectedIndex(categoryNames.indexOf(cv.currentItem[fieldName])); } else { controls[fieldName].setValue(cv.currentItem[fieldName]); } } } const setEnabled = (isEnabled) => { for (var fieldName in controls) { controls[fieldName].setEnabled(isEnabled); } } const switchForms = () => { const editForm = document.getElementById('editForm'); const commitForm = document.getElementById('commitForm'); editForm.style.display = editForm.style.display == 'block' ? 'none' : 'block'; commitForm.style.display = commitForm.style.display == 'block' ? 'none' : 'block'; } const btn_contanier = document.getElementById('btn_container'); btn_contanier.addEventListener('click', (e) => { let name = e.target.getAttribute('name'); if (!name) { return; } handler[name](); }); const handler = { edit: () => { cv.editItem(cv.currentItem); setEnabled(true); switchForms(); }, add: () => { cv.addNew(); setEnabled(true); switchForms(); }, remove: () => { cv.remove(cv.currentItem); }, commit: () => { for (var fieldName in controls) { cv.currentItem[fieldName] = fieldName == '分類' ? categoryNames[controls[fieldName].getSelectedIndex()] : controls[fieldName].getValue(); } cv.commitEdit(); cv.commitNew(); setEnabled(false); switchForms(); }, cancel: () => { cv.cancelEdit(); cv.cancelNew(); setEnabled(false); switchForms(); }, moveCurrentToFirst: () => cv.moveCurrentToFirst(), moveCurrentToPrevious: () => cv.moveCurrentToPrevious(), moveCurrentToNext: () => cv.moveCurrentToNext(), moveCurrentToLast: () => cv.moveCurrentToLast(), } update(); setEnabled(false);
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>基本機能 - Wijmoとのデータ連携</title> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> window.onload = function() { System.import('./src/app'); } </script> </head> <body> <table id="btn_container"> <tr> <td style="min-width: 300px;"> <table> <tr> <td>商品コード</td> <td><input id="商品コード"></td> </tr> <tr> <td>商品名</td> <td><input id="商品名"></td> </tr> <tr> <td>分類</td> <td><select id="分類"></select></td> </tr> <tr> <td>価格</td> <td><input id="価格"></td> </tr> <tr> <td>発売日</td> <td><input id="発売日"></td> </tr> </table><br> <div id="editForm" style="display: block;"> <button name="edit">編集</button> <button name="add">追加</button> <button name="remove">削除</button> </div> <div id="commitForm" style="display: none;"> <button name="commit">確定</button> <button name="cancel">キャンセル</button> </div> <div> <button name="moveCurrentToFirst">&lt;&lt;</button> <button name="moveCurrentToPrevious">&lt;</button> <button name="moveCurrentToNext">&gt;</button> <button name="moveCurrentToLast">&gt;&gt;</button> </div> </td> <td> <div id="grid" style="height: 15rem;"></div> </td> </tr> </table><br> <table style="table-layout: fixed; width: 100%;"> <tr> <td> <label>編集された項目:<div id="gridEdited" style="height: 6.5rem;"></div></label> </td> <td> <label>追加された項目:<div id="gridAdded" style="height: 6.5rem;"></div></label> </td> </tr> <tr> <td> <label>削除された項目:<div id="gridRemoved" style="height: 6.5rem;"></div></label> </td> <td> </td> </tr> </table> </body> </html>
.gcim, .gcim-calendar { width: 200px; }
import { Globalize } from '@mescius/wijmo'; export const getProducts = () => { let products = []; let id = 1; let date = new Date(2014, 0, 1); for (let i = 0; i < productNames.length; i++) { for (let j = 0; j < productNames[i].length; j++) { products.push({ 商品コード: 'P' + Globalize.format(id++, 'd3'), 商品名: productNames[i][j], 分類: categoryNames[i], 価格: random(40, 10) * 100, 発売日: addDays(date, random(365 * 4)) }); } } return products; } const random = (max, min) => { if (!min) min = 0; return Math.floor(Math.random() * (max - min)) + min; } const addDays = (value, days) => { return new Date(value.getFullYear(), value.getMonth(), value.getDate() + days); } const productNames = [ ['果汁100%オレンジ', '果汁100%グレープ', '果汁100%レモン', '果汁100%ピーチ', 'コーヒーマイルド', 'コーヒービター', 'コーヒーミルク', 'ピリピリビール', 'オタル白ラベル', 'バードワイン'], ['ホワイトソルト', 'ブラックペッパー', 'ピュアシュガー', 'うまい素', 'ピュアデミグラスソース', 'だしかつお', 'だしこんぶ', 'ピリカラタバスコ', 'のり山椒', '特製和風醤油'], ['バニラクリームアイス', 'チョコクリームアイス', '紅茶バー', 'じゃがチップス', 'アメリカンクラッカー', 'バナナキャンディー', 'メロンミルクキャンディー', '小倉あんぱん', 'インドカレーパン', 'チーズあんぱん'], ['ロッキーチーズ', 'パルメザンチーズ', 'フレッシュバター', 'ライフマーガリン', 'ローカロリー牛乳', '牛乳マイルド', 'ストロベリーヨーグルト', 'ブルーベリーヨーグルト', 'ラズベリーヨーグルト', 'ココナッツミルク'], ['モーニングブレッド', 'バタートースト', 'バケットフランス', '極上パスタ', '極上マカロニ', '伝統スパゲッティ', 'ヘルシークラッカー', 'コーンフレークプレーン', 'コーンフレークチョコ', 'コーンフレークシュガー'], ['アメリカンポーク', 'うす味ウインナー', 'ベターローストハム', 'ベタープレスハム', 'ベター生ハム', '特製サラミ', '和風ハンバーグレトルト', '照焼きミートボール', 'ミックスハム', 'ミートバー'], ['もめんどうふ特上', 'きぬごしどうふ特上', '冷凍ミックスベジタブル', '冷凍クリームコロッケ', '冷凍コーンクリームコロッケ', '冷凍ポテトコロッケ', '冷凍枝豆', '冷凍やきおにぎり', '乾燥バナナ', '乾燥アップル'], ['特選味のり', '北海道昆布', 'やきいかするめくん', '食卓わかめ', 'ふりかけかつお風味', 'ふりかけ鮭風味', '大陸サーモン', '特選にぼし', '本がつお特上', 'ころもはんぺん'] ]; export const categoryNames = ['飲料', '調味料', '菓子類', '乳製品', '穀類、シリアル', '肉類', '加工食品', '魚介類'];
[gcim-control-appearance="modern"] .gcim, [gcim-control-appearance="modern"] .gcim-calendar { width: 200px; }
System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { '@mescius/inputman': 'npm:@mescius/inputman/index.js', '@mescius/inputman/CSS': 'npm:@mescius/inputman/CSS', '@mescius/wijmo': 'npm:@mescius/wijmo/index.js', '@mescius/wijmo.styles': 'npm:@mescius/wijmo.styles', '@mescius/wijmo.cultures': 'npm:@mescius/wijmo.cultures', '@mescius/wijmo.input': 'npm:@mescius/wijmo.input/index.js', '@mescius/wijmo.grid': 'npm:@mescius/wijmo.grid/index.js', 'css': 'npm:systemjs-plugin-css/css.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build': 'npm:systemjs-plugin-babel/systemjs-babel-browser.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'js' }, "node_modules": { defaultExtension: 'js' }, } });