Wijmo

FlexGrid入門

このページでは、WijmoのFlexGridコントロールを使い始める方法を示します。

はじめに

FlexGridをJavaScriptアプリケーションで使用する手順は以下のとおりです。

  1. Wijmoへの参照を追加します。
  2. Wijmoコントロールのホストとして機能するマークアップを追加します。
  3. JavaScriptを使用してWijmoコントロールを初期化します。
  4. (オプション)FlexGridコントロールの外観をカスタマイズするためのCSSを追加します。

これはFlexGridの自動列生成、列ソート、編集、クリップボードのサポートが含まれるデフォルト動作を作成します。

<!DOCTYPE html> <html> <head> <link rel="stylesheet" type="text/css" href="css/bootstrap.css"/> <link rel="stylesheet" type="text/css" href="css/wijmo.css" /> <link href="css/app.css" rel="stylesheet" type="text/css" /> <script src="scripts/wijmo.js" type="text/javascript"></script> <script src="scripts/wijmo.input.js" type="text/javascript"></script> <script src="scripts/wijmo.grid.js" type="text/javascript"></script> </head> <body> <!-- this is the grid --> <div id="gsFlexGrid"></div> </body> </html>
var countries = 'US,Germany,UK,Japan,Italy,Greece'.split(','); var data = []; for (var i = 0; i < count; i++) { data.push({ id: i, country: countries[i % countries.length], date: new Date(2014, i % 12, i % 28), amount: Math.random() * 10000, active: i % 4 === 0 }); } // create the grid and give it some data var grid = new wijmo.grid.FlexGrid('#gsFlexGrid'); grid.itemsSource = data;
/* set default grid style */ .wj-flexgrid { height: 300px; background-color: white; box-shadow: 4px 4px 10px 0px rgba(50, 50, 50, 0.75); margin-bottom: 12px; }

結果(ライブ):

列定義

「はじめに」の例では列を定義していなかったため、FlexGridが自動的に列を生成しました。

この例は、FlexGridのinitializeメソッドとcolumnsコレクションを直接使用して列を定義する方法を示しています。

列を指定すると、表示する列とその順序を設定できます。 また、各列の幅、見出し、書式設定、配置などのプロパティも制御できます。

このケースでは、スターサイズ指定を使用して[Country]列の幅を設定しています。これにより、[Country]列が拡張されてグリッドの使用可能な幅が満たされるため、空スペースがなくなります。[Revenue]列ではformatプロパティが"n0"に設定されており、この列の数値が桁区切り文字付き、小数点なしになっています。

<b>Initialize Method</b> <div id="cdInitMethod"></div> <b>列定義</b> <div id="cdColsCollection"></div>
// create two grids and some data var fgInitMethod = new wijmo.grid.FlexGrid('#cdInitMethod'), fgColsCollection = new wijmo.grid.FlexGrid('#cdColsCollection'), cv = new wijmo.collections.CollectionView(data.getData(100)); // initialize one grid using 'initialize' method fgInitMethod.initialize({ autoGenerateColumns: false, columns: [ { header: 'Country', binding: 'country', width: '*' }, { header: 'Date', binding: 'date' }, { header: 'Revenue', binding: 'amount', format: 'n0' }, { header: 'Active', binding: 'active' }, ], itemsSource: cv }); // initialize the other grid using the columns collection fgColsCollection.autoGenerateColumns = false; fgColsCollection.itemsSource = cv; var c = new wijmo.grid.Column(); c.binding = 'country'; c.header = 'Country'; c.width = '*'; fgColsCollection.columns.push(c); c = new wijmo.grid.Column(); c.binding = 'date'; c.header = 'Date'; fgColsCollection.columns.push(c); c = new wijmo.grid.Column(); c.binding = 'amount'; c.header = 'Revenue'; c.format = 'n0'; fgColsCollection.columns.push(c); c = new wijmo.grid.Column(); c.binding = 'active'; c.header = 'Active'; fgColsCollection.columns.push(c);

結果(ライブ):

Initialize Method
Columns Collection

選択モード

デフォルトでは、FlexGridではExcelと同様にマウスまたはキーボードを使用してセルの範囲を選択できます。selectionModeプロパティを使用してこのデフォルトの動作を変更し、行、行の範囲、隣接していない行(リストボックスと同様)、または単一セルを選択できるようにするか、あるいはまったく選択できないようにするかを指定できます。

この例では、Wijmo MenuコントロールからselectionModeを選択できます。

<div id="smFlexGrid"></div> <select id="smMenu"> <option value="None">None</option> <option value="Cell">Cell</option> <option value="CellRange" selected>CellRange</option> <option value="Row">Row</option> <option value="RowRange">RowRange</option> <option value="ListBox">ListBox</option> </select>
// initialize grid and menu var grid = new wijmo.grid.FlexGrid('#smFlexGrid'), menu = new wijmo.input.Menu('#smMenu'), cv = new wijmo.collections.CollectionView(data.getData(100)); grid.itemsSource = cv; updateMenuHeader(); // update grid selection mode when an item is selected from the menu menu.itemClicked.addHandler(function (sender) { grid.selectionMode = sender.selectedValue; updateMenuHeader(); }); // update menu header to show current selection mode function updateMenuHeader() { menu.header = '<b>選択モード:</b> ' + menu.text; }

結果(ライブ):

編集

FlexGridは、Excelに似た迅速なセル内編集を組み込みでサポートしています。表示モードと編集モードを切り替える[編集]ボタンを含む列を追加する必要はありません。

ユーザーはセルに文字を入力することによって編集を開始できます。この場合、セルはクイック編集モードになります。このモードでは、方向キーを押すと編集が終了し、選択が別のセルに移動します。

また、[F2]を押すかセルをダブルクリックすることによって編集を開始することもできます。この場合、セルはフル編集モードになります。このモードでは、方向キーを押すとセルテキスト内でキャレットが移動します。編集を終了して別のセルに移動するためには、[Enter]、[Tab]、[Esc]のいずれかのキーを押す必要があります。

編集を終了するとき、データは適切な型に自動的に型変換されます。ユーザーが無効なデータを入力した場合、編集はキャンセルされ、元のデータに戻ります。

グリッド、列、または行レベルで編集を無効にするには、グリッド、列、または行オブジェクトのisReadOnlyプロパティを使用します。この例では、[ID]列が読み取り専用になっています。

<div id="eFlexGrid"></div>
// create and initialize grid (editing is enabled by default) var grid = new wijmo.grid.FlexGrid('#eFlexGrid', { autoGenerateColumns: false, columns: [ { header: 'ID', binding: 'id', width: '*', isReadOnly: true }, // cannot edit { header: 'Country', binding: 'country' }, { header: 'Date', binding: 'date' }, { header: 'Revenue', binding: 'amount', format: 'n0' }, { header: 'Active', binding: 'active' }, ], itemsSource: data.getData(100) });

結果(ライブ):

グループ化

FlexGridは、ICollectionViewインタフェース(これは.NETのICollectionViewインタフェースと同一です)によってグループ化をサポートします。グループ化を有効にするには、1つ以上のGroupDescriptionオブジェクトをCollectionView.groupDescriptionsプロパティに追加し、グリッドのshowGroupsプロパティをtrue(デフォルト値)に設定します。

GroupDescriptionオブジェクトは柔軟性が高く、値またはグループ化関数に基づいてデータをグループ化できます。 この例では、日付(年別)、金額(5,000超、500~5,000、500未満の3つの範囲別)、およびその他の項目(値別)でグループ化できます。 メニューを使用して各グループ化の効果を確認してください。

[Revenue]列にはグループ行の合計が表示されます。このようにするには、列のaggregateプロパティを"Sum"に設定します。列の値を編集すると、集計は自動的に更新されます。

<div id="gFlexGrid"></div> <select id="gMenu"> <option value="" selected>(グループ化なし)</option> <option value="country">Country</option> <option value="amount">Revenue</option> <option value="date">Date</option> <option value="country,date">Country、Date</option> <option value="country,amount">Country、Revenue</option> <option value="country,date,amount">Country、Date、Revenue</option> </select>
// initialize grid and menu var grid = new wijmo.grid.FlexGrid('#gFlexGrid'), menu = new wijmo.input.Menu('#gMenu'), cv = new wijmo.collections.CollectionView(data.getData(100)); grid.initialize({ autoGenerateColumns: false, columns: [ { header: 'Country', binding: 'country', width: '*' }, { header: 'Date', binding: 'date' }, { header: 'Revenue', binding: 'amount', format: 'n0' } ], itemsSource: cv }); updateMenuHeader(); // handle the Menu control's selectedIndexChanged event menu.itemClicked.addHandler(function (sender) { var groupBy = sender.selectedValue; cv.groupDescriptions.clear(); if (groupBy) { var groupNames = groupBy.split(','); for (var i = 0; i < groupNames.length; i++) { var groupName = groupNames[i]; if (groupName == 'date') { // group dates by year var groupDesc = new wijmo.collections.PropertyGroupDescription(groupName, function (item, prop) { return item.date.getFullYear(); }); cv.groupDescriptions.push(groupDesc); } else if (groupName == 'amount') { // group amounts in ranges var groupDesc = new wijmo.collections.PropertyGroupDescription(groupName, function (item, prop) { return item.amount >= 5000 ? '> 5,000' : item.amount >= 500 ? '500 to 5,000' : '< 500'; }); cv.groupDescriptions.push(groupDesc); } else { // group everything else by value var groupDesc = new wijmo.collections.PropertyGroupDescription(groupName); cv.groupDescriptions.push(groupDesc); } } } updateMenuHeader(); }); // show currently selected item function updateMenuHeader() { menu.header = '<b>グループ化:</b> ' + menu.text; }

結果(ライブ):

フィルタリング

FlexGridは、ICollectionViewインタフェース(これは.NETのICollectionViewインタフェースと同一です)によってフィルタリングをサポートします。フィルタリングを有効にするには、ビューに含めるオブジェクトを決定する関数をCollectionView.filterプロパティに設定します。

この例では、国のフィルタを作成し、入力コントロールからフィルタ値を取得します。

<div id="fFlexGrid"></div> <div class="input-group"> <span class="input-group-addon"> <i class="glyphicon glyphicon-filter"></i> </span> <input id="fFilter" type="text" class="form-control" placeholder="Filter by Country..." /> </div>
// create grid, some data var grid = new wijmo.grid.FlexGrid('#fFlexGrid'), cv = new wijmo.collections.CollectionView(data.getData(100)), filterEl = document.getElementById('fFilter'), filterText = ''; // populate the grid with data grid.itemsSource = cv; // update grid when filter changes filterEl.addEventListener('input', function () { filterText = this.value.toLowerCase(); cv.refresh(); }); // CollectionView filter cv.filter = function (item) { return !filterText || item.country.toLowerCase().indexOf(filterText) > -1; };

結果(ライブ):

ページング

FlexGridは、IPagedCollectionViewインタフェース(これは.NETのIPagedCollectionViewインタフェースと同一です)によってページングをサポートします。ページングを有効にするには、各ページに表示する項目数をIPagedCollectionView.pageSizeプロパティに設定し、ページを移動するためのUIを提供します。

この例では、JavaScriptを使用して1ページに10項目を表示しています。ナビゲーションボタンが用意されており、ボタンをクリックするとIPagedCollectionViewメソッドが呼び出されます。また、pageIndexプロパティとpageCountプロパティを使用して現在のページと総ページ数を表示しています。

<div id="pFlexGrid" style="height:auto"></div> <div class="btn-group" id="pPager"> <button type="button" class="btn btn-default" data-action="fast-backward" id="pfb"> <span class="glyphicon glyphicon-fast-backward"></span> </button> <button type="button" class="btn btn-default" data-action="step-backward" id="psb"> <span class="glyphicon glyphicon-step-backward"></span> </button> <button type="button" class="btn btn-default" disabled style="width:100px" data-action="none" id="pn"></button> <button type="button" class="btn btn-default" data-action="step-forward" id="psf"> <span class="glyphicon glyphicon-step-forward"></span> </button> <button type="button" class="btn btn-default" data-action="fast-forward" id="pff"> <span class="glyphicon glyphicon-fast-forward"></span> </button> </div>
// create a CollectionView, set the page size to 10, initialize pager var cv = new wijmo.collections.CollectionView(data.getData(100)), pagerButtons = Array.prototype.slice.call(document.querySelectorAll('#pPager button')); cv.pageSize = 10; // set collectionView's pageSize updatePager(); // show the data in a grid var grid = new wijmo.grid.FlexGrid('#pFlexGrid'); grid.itemsSource = cv; // update pager when user clicks a button pagerButtons.forEach(function(el) { el.addEventListener('click', function () { updatePager(this.getAttribute('data-action')); }); }); // disable/enable buttons and update display text for pager function updatePager(action) { // get buttons by id var display = document.getElementById('pn'), fb = document.getElementById('pfb'), sb = document.getElementById('psb'), sf = document.getElementById('psf'), ff = document.getElementById('pff'), enableBackwards = false, enableForwards = false; // handle pager operation based on button's attribute switch (action) { case 'fast-backward': cv.moveToFirstPage(); break; case 'step-backward': cv.moveToPreviousPage(); break; case 'step-forward': cv.moveToNextPage(); break; case 'fast-forward': cv.moveToLastPage(); break; } // update the pager text display.innerHTML = (cv.pageIndex + 1) + ' / ' + (cv.pageCount); // determine which pager buttons to enable/disable enableBackwards = cv.pageIndex <= 0; enableForwards = cv.pageIndex >= cv.pageCount - 1; // enable/disable pager buttons fb.disabled = enableBackwards; sb.disabled = enableBackwards; sf.disabled = enableForwards; ff.disabled = enableForwards; }

結果(ライブ):

マスター/詳細

ICollectionViewインタフェースはカレンシー(現在の項目)を組み込みでサポートしているため、FlexGridでマスター/詳細シナリオを実装できます。 currentItemを参照し、それをページの要素のバインディングソースとして使用できます。

現在のアイテムが変更されたときに、詳細ビューを更新する必要があることに注意してください。 そのためには、ハンドラーをICollectionView.currentChangedイベントにアタッチし、必要に応じて詳細ビューを更新します。

<div id="mdFlexGrid"></div> <dl class="dl-horizontal"> <dt>ID</dt> <dd id="mdCurId"></dd> <dt>Country</dt> <dd id="mdCurCountry"></dd> <dt>Date</dt> <dd id="mdCurDate"></dd> <dt>Revenue</dt> <dd id="mdCurRevenue"></dd> <dt>Active</dt> <dd id="mdCurActive"></dd> </dl>
// create a CollectionView to keep track of selection var cv = new wijmo.collections.CollectionView(data.getData(100)); // initialize details pane updateDetails(); // update details when current item changes cv.currentChanged.addHandler(function (sender, args) { updateDetails(); }); // create a grid to show/edit the data var grid = new wijmo.grid.FlexGrid('#mdFlexGrid', { autoGenerateColumns: false, columns: [ { header: 'Country', binding: 'country', width: '*' }, { header: 'Date', binding: 'date' } ], itemsSource: cv }); // update the details when the CollectionView's currentItem changes function updateDetails() { var item = cv.currentItem; document.getElementById('mdCurId').innerHTML = item.id; document.getElementById('mdCurCountry').innerHTML = item.country; document.getElementById('mdCurDate').innerHTML = wijmo.Globalize.format(item.date, 'd'); document.getElementById('mdCurRevenue').innerHTML = wijmo.Globalize.format(item.amount, 'c'); document.getElementById('mdCurActive').innerHTML = item.active; }

結果(ライブ):

ID
Country
Date
Revenue
Active

条件付きスタイル設定

FlexGridでは、itemFormatterプロパティを使用してセルの内容を完全に制御できます。

この例では、JavaScript関数を使用して、名前付きの色を返す値範囲を作成しています。 次に、FlexGridのitemFormatterでこの関数を呼び出し、条件付きでセルの前景色を設定するためにセルのデータを渡します。

<div id="csFlexGrid"></div>
// create grid, some data var grid = new wijmo.grid.FlexGrid('#csFlexGrid'), cv = new wijmo.collections.CollectionView(data.getData(100)); // initialize grid grid.initialize({ autoGenerateColumns: false, columns: [ { header: 'Country', binding: 'country', width: '*', isContentHtml: true, isReadOnly: true }, { header: 'Date', binding: 'date' }, { header: 'Revenue', binding: 'amount', format: 'n0' }, { header: 'Active', binding: 'active' }, ], itemsSource: cv, itemFormatter: function (panel, r, c, cell) { // we are only interested in regular (scrollable) cells if (wijmo.grid.CellType.Cell === panel.cellType) { // compute the cell color // (for all columns, since cells may be recycled) var color = ''; if (panel.columns[c].binding == 'amount') { var cellData = panel.getCellData(r, c); color = getAmountColor(cellData); } // always set the color cell.style.color = color; } } }); // get the color used to display an amount function getAmountColor(amount) { return amount < 500 ? 'red' : amount < 2500 ? 'black' : 'green'; }

結果(ライブ):

テーマ

FlexGridの外観はCSSで定義されます。デフォルトテーマに加えてプロフェッショナルなデザインのテーマが多数用意されており、すべてのWijmoコントロールの外観をカスタマイズして一貫性のある魅力的な見た目を提供できます。

グリッドの外観はCSSを使用してカスタマイズできます。そのためには、デフォルトテーマから新しいCSSファイルにCSSルールをコピーし、必要なスタイル属性を変更します。

この例では、"custom-flex-grid"クラスをグリッド要素に追加し、"custom-flex-grid"クラスを持つグリッド用に白黒および罫線なしのシンプルなテーマを作成するCSSルールを定義しています。

<div id="tFlexGrid" class="custom-flex-grid"></div>
var grid = new wijmo.grid.FlexGrid('#tFlexGrid'); grid.itemsSource = data.getData(100);
.custom-flex-grid .wj-header.wj-cell { color: #fff; background-color: #000; border-bottom: solid 1px #404040; border-right: solid 1px #404040; font-weight: bold; } .custom-flex-grid .wj-cell { background-color: #fff; border: none; } .custom-flex-grid .wj-alt:not(.wj-state-selected):not(.wj-state-multi-selected) { background-color: #fff; } .custom-flex-grid .wj-state-selected { background: #000; color: #fff; } .custom-flex-grid .wj-state-multi-selected { background: #222; color: #fff; }

結果(ライブ):

ツリーと階層データ

グループ化に加えて、FlexGridは階層データ(サブ項目のリストを持つ項目で構成されたデータ)もサポートします。この種の階層構造は非常に一般的で、通常はツリー表示コントロールで表示されます。

FlexGridで階層データソースを使用するには、子要素を含むデータ要素の名前をchildItemsPathプロパティに設定します。グリッドがデータを自動的にスキャンしてツリーを構築します。

<div id="tvFlexGrid" class="custom-flex-grid"></div>
// create the grid var grid = new wijmo.grid.FlexGrid('#tvFlexGrid'); // populate the grid and set childItemsPath to show data hierarchically grid.childItemsPath = 'items'; // initialize the grid to show hierarchical data grid.initialize({ autoGenerateColumns: false, columns: [ { binding: 'name', width: '*' }, { binding: 'length', width: 80, align: 'center' } ], itemsSource: data.treeData, // hierarchical data childItemsPath: 'items', // set hierarchy path allowResizing: wijmo.grid.AllowResizing.None, // disable resizing headersVisibility: wijmo.grid.HeadersVisibility.None, // hide headers selectionMode: wijmo.grid.SelectionMode.ListBox // use ListBox selection });
.custom-flex-grid .wj-header.wj-cell { color: #fff; background-color: #000; border-bottom: solid 1px #404040; border-right: solid 1px #404040; font-weight: bold; } .custom-flex-grid .wj-cell { background-color: #fff; border: none; } .custom-flex-grid .wj-alt:not(.wj-state-selected):not(.wj-state-multi-selected) { background-color: #fff; } .custom-flex-grid .wj-state-selected { background: #000; color: #fff; } .custom-flex-grid .wj-state-multi-selected { background: #222; color: #fff; }

結果(ライブ):

null値の扱い

デフォルトでは、FlexGridは文字列型の列に空文字を入力することができ、他の列型では空文字やnull値を許容しません。

isRequiredプロパティをグリッドの列に設定することでこの動作を変更することができます。 isRequiredプロパティをfalseに設定すると、列型に関わらず空文字の入力を許容することができます。 逆にtrueに設定すると、文字列型であっても空文字の入力を許容しません。

isRequiredにnullを設定すると、デフォルト動作(文字列型のみ空文字の入力を許容する)に戻ります。

グリッドは以下のデフォルト動作に戻します。 最初の列にisRequiredをtrueに設定し、他の列はfalseに設定します。 空文字を入力する、またはDeleteキーによってコンテンツを削除することができます。

<div id="nvGrid"></div>
// create a grid and define the columns new wijmo.grid.FlexGrid('#nvGrid', { autoGenerateColumns: false, itemsSource: data.getData(100), columns: [ { header: 'Country', binding: 'country', width: '*', is-required: true }, { header: 'Date', binding: 'date', is-required: false }, { header: 'Revenue', binding: 'amount', format: 'n0', is-required: false }, { header: 'Active', binding: 'active', is-required: false } ] });

結果(ライブ):