[]
このサンプルでは、Wijmo Web Componentsのベータ版を紹介します。Wijmo Web Componentsを使用すると、WijmoコントロールのカスタムタグをHTMLページに追加し、追加のフレームワークを使用せずに通常のDOMエレメントとして操作できます。Web Components標準を完全にサポートしていないブラウザーでは、いくつかの追加のポリフィルが必要になる場合があります。
Web Componentsに精通していない場合は、技術紹介情報を参照してください。
Wijmo Web Componentsの現在の実装状態は次の通りです。
Wijmoコントロールを表すトップレベルのWebコンポーネント(例:FlexGridコントロールを表すwjc-flex-gridコンポーネント)は、対応するコントロールクラスから継承されます。 たとえば、WjcFlexGridコンポーネントクラスはFlexGridコントロールクラスを継承します。
これは、WijmoがWebComponentsモードで使用されている場合、WijmoのControl基本クラスがHTMLElementクラスを拡張することを意味します。
FlexGridカラムを定義するwjc-flex-grid-columnコンポーネントのような最上位コンポーネントを補完する子コンポーネントは、それらが表すWijmoクラスの上にラッパーとして機能します。 子コンポーネントはHTMLElementクラスから直接継承され、基になるWijmoクラスインスタンスはコンポーネントの特別なcontrolプロパティを介してアクセスできます。
Wijmoクラスのプロパティは、コンポーネント要素の属性を使用して定義できます。 属性値が変更されると、対応するWijmoクラスプロパティがそれに応じて更新されます。 クラスプロパティの値を変更しても、対応する属性値は変更されません。 これは将来変更される可能性がありますが、今必要かどうかについては決定していません。
JavaScriptコードは、ネイティブのElement.addEventListener('event', handler)メソッドを使用してWijmoコントロールイベントにハンドラを登録できます。
Wijmoコンポーネントは現在Shadow DOMを使用していません。 これは将来のバージョンで対応予定です。 ここでの課題の1つは、WijmoがCSSを使用してコントロールのパーツを詳細にカスタマイズできることですが、一方でShadow DOMの目的はそれを防ぐことです。 この制限を緩和することができるShadow DOM仕様の新しい提案があります。 私たちはその変更を追跡し続けています。 現時点では、Wijmo Webコンポーネントとその部品は、グローバルCSSを使用して、通常のWijmoコントロールと同じ方法でカスタマイズできます。
Wijmo Webコンポーネント相互運用モジュールを使用すると、次の例に示すように、HTMLマークアップにコントロールのタグを追加できます。
<label >InputNumber</label>
<wjc-input-number value="5" step="3"></wjc-input-number>
<label>FlexGrid with Filter and specific columns</label>
<wjc-flex-grid id="gridIntro">
<wjc-flex-grid-filter></wjc-flex-grid-filter>
<wjc-flex-grid-column binding="country" header="Country" width="*">
</wjc-flex-grid-column>
<wjc-flex-grid-column binding="date" header="Date">
</wjc-flex-grid-column>
<wjc-flex-grid-column binding="downloads" header="Downloads">
</wjc-flex-grid-column>
</wjc-flex-grid>
let gridIntro = document.getElementById('gridIntro');
gridIntro.itemsSource = dataSvc.getData(100);
このサンプルはnpmモジュールに基づいており、SystemJSランタイムモジュールローダーまたはWebpackバンドラーを使用して実行するように構成されています。
WebComponentsベースのアプリケーション構成の重要な側面は次のとおりです。
コマンドプロンプトでWijmoをインストールします。
npm install @mescius/wijmo.webcomponents.all@nightly --save
WebComponentsポリフィルをインストールします。
npm install @webcomponents/webcomponentsjs --save
それらをルートページ(default.htm)に追加します。
このポリフィルは、Webコンポーネントを含むアプリケーションをES5コードとして実行する場合にのみ必要です。
<script src="node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
このポリフィルは、Chrome以外のすべてのブラウザで必要です。
<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
ルートHTMLページで次の設定を行い、WijmoのWebComponentsモードを有効にします。これはWijmoモジュールが読み込まれる前に実行する必要があります。
<script>
window['wj-control-is-element'] = true;
</script>
この割り当てによって、WijmoのControlクラスは、通常のようにObjectクラスではなく、HTMLElementクラスを拡張します。
Wijmo WebComponentsの必要なモジュールをES6/TypeScriptコードでインポートします。
import '@mescius/wijmo.webcomponents.input';
import '@mescius/wijmo.webcomponents.grid';
これらのインポートによって、モジュールはwindow.customElements.define()メソッドを使用してWebコンポーネントをグローバルに登録します。
(注:このサンプルには該当しません) Wijmo WebComponents相互運用モジュールをグローバルモジュールとして使用する場合は、Wijmo製品版/トライアル版のzipファイルのdist\interop\webcomponentsフォルダにあるwijmo.webcomponents.jsファイルを、<script>
タグを使用してルートhtmlページに追加する必要があります。
<script src="path_to_wijmo/dist/interop/webcomponents/wijmo.webcomponents.js"></script>
この1つのファイルには、相互運用モジュールによって提供されるすべてのコンポーネントが含まれています。
これで、Wijmo Webコンポーネントをアプリケーションで使用できます。
<head>
<script src="node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
<script>
window['wj-control-is-element'] = true;
</script>
...
</head>
<body>
<wjc-input-number value="5" step="3"></wjc-input-number>
</body>
import '@mescius/wijmo.webcomponents.input';
プロパティ値は、Wijmo Webコンポーネント要素の対応する属性を使用して指定できます。
次のルールを考慮する必要があります。
属性名はダッシュ区切り形式で指定する必要があります。例えば、firstDayOfWeekプロパティの値はfirst-week-week属性で指定します。
単純な型のプロパティだけを属性として指定できます。 列挙型のプロパティの場合は、**selection-mode="Day"**のように列挙型メンバー名を使用できます。
属性値は常に文字列であるため、Wijmo Webコンポーネントは対応するプロパティに値を割り当てる前に適切な値の変換を行います。
次の例は、異なる型のプロパティが指定されたwjc-calendarWebコンポーネントを示しています。
<label>Calendar</label>
<wjc-calendar style="width:450px"
show-header="true"
value="04/07/2018"
first-day-of-week="1"
selection-mode="Day"
format-day-headers="dddd">
</wjc-calendar>
Wijmo Controlsを表すトップレベルのWebコンポーネントに加えて、親コンポーネントの設定をタグでカスタマイズするのに役立つ子コンポーネントもあります。 たとえば、wjc-flex-grid-columnコンポーネントを使用してFlexGrid列のリストを指定したり、wjc-flex-chart-series子コンポーネントを使用してFlexChartシリーズを定義できます。
子コンポーネントは親コンポーネントの直接の子でなければなりません。
以下に例を示します。
wjc-flex-gridコンポーネントには、グリッド列のリストを定義するwjc-flex-grid-column子コンポーネントと、グリッドに列フィルタを適用するwjc-flex-grid-filter子コンポーネントが含まれます。
wjc-flex-chartコンポーネントには、チャートのシリーズを定義するwjc-flex-chart-series子コンポーネントと、チャートのX軸とY軸をカスタマイズするwjc-flex-chart-axisコンポーネントが含まれます。
<label>FlexGrid with Columns and Filter</label>
<wjc-flex-grid id="gridWithChildren" style="height:auto">
<wjc-flex-grid-filter></wjc-flex-grid-filter>
<wjc-flex-grid-column binding="country"
header="Country"
width="*">
</wjc-flex-grid-column>
<wjc-flex-grid-column binding="date" header="Date">
</wjc-flex-grid-column>
<wjc-flex-grid-column binding="downloads" header="Downloads">
</wjc-flex-grid-column>
<wjc-flex-grid-column binding="sales" header="Sales" format="c2">
</wjc-flex-grid-column>
</wjc-flex-grid>
<label>FlexChart with Series and Axes</label>
<wjc-flex-chart id="chartWithChildren" binding-x="country" style="height:300px">
<wjc-flex-chart-axis
wj-property="axisX"
title="Countries"
axis-line="true">
</wjc-flex-chart-axis>
<wjc-flex-chart-axis
wj-property="axisY"
title="Sales/Downloads"
axis-line="true"
major-grid="true">
</wjc-flex-chart-axis>
<wjc-flex-chart-series name="Sales" binding="sales">
</wjc-flex-chart-series>
<wjc-flex-chart-series name="Downloads" binding="downloads">
</wjc-flex-chart-series>
</wjc-flex-chart>
document.getElementByIdメソッドのような従来のDOM APIを使用して、Wijmo Webコンポーネント要素を取得することができます。 その後、次のルールに従って、この要素のWijmo固有のAPIにアクセスできます。
Wijmoコントロールを表す最上位レベルのコンポーネントの場合、対応するコントロールクラスから直接継承されるため、すべてのコントロールのAPIは要素のすぐ下にあります。 たとえば、次のコードを使用してFlexGrid Webコンポーネントにデータを割り当てることができます。
document.querySelector('wjc-flex-grid').itemsSource = getData();
Wijmoコントロールに付属する子コンポーネントの場合、Wijmoの子コンポーネントは対応するWijmoクラスのラッパーとして機能するため、特別なcontrolプロパティを使用して、基になるWijmoオブジェクトへの参照を取得する必要があります。 たとえば、このコードを使用してFlexGridFilter Webコンポーネントのフィルタ列リストを指定できます。
document.querySelector('wjc-flex-grid-filter').control.filterColumns = ['country', 'date'];
次の例では、wjc-flex-gridコンポーネントにwjc-group-panelコンポーネントを添付して、wjc-flex-grid-filterコンポーネントにフィルタ列リストを定義します。
<label>FlexGrid with GroupPanel and Filter</label>
<wjc-group-panel
id="panelRef"
placeholder="Drag columns here...">
</wjc-group-panel>
<wjc-flex-grid id="gridRef">
<wjc-flex-grid-filter id="filterRef"></wjc-flex-grid-filter>
</wjc-flex-grid>
// Find grid element in the DOM tree
let gridRef = document.getElementById('gridRef');
// The element is also a FlexGrid instance (inherited from FlexGrid),
// so we can use FlexGrid api on the element, e.g. to assign its data
// source.
gridRef.itemsSource = dataSvc.getData(100);
// Find group panel element in the DOM tree
let panelRef = document.getElementById('panelRef');
// and attach it to the grid:
panelRef.grid = gridRef;
// Find wjc-flex-grid-filter component in the DOM tree
let filterRef = document.getElementById('filterRef');
// and specify the filterColumns property value of its
// underlying FlexGridFilter object
filterRef.control.filterColumns = ['country', 'date'];
ネイティブHTML要素と同様に、従来のaddEventListenerメソッドを使用して、Wijmo固有のイベントを処理することができます。 イベント名はダッシュ区切り形式で指定する必要があります。例えば、WijmoネイティブのvalueChangedイベントの場合はvalue-changedになります。
たとえば、次のようなコードを使用して、対応するWebコンポーネントのInputNumber.valueChangedイベントを処理することができます。
document.querySelector('wjc-input-number').addEventListener('value-changed', (e) => {
alert(`New value is ${e.target.value}`);
});
Wijmoコンポーネントは、CustomEvent型のイベントをトリガします。 イベントハンドラで使用できるイベントオブジェクトには、次の2つの主要なプロパティがあります。
target - イベントをトリガーしたWebコンポーネントを参照します。
detail - 対応するWijmoイベントのイベント引数を保持します。 たとえば、FlexGrid.formatItemイベントの場合、CustomEvent.detailプロパティにFormatItemEventArgs型のオブジェクトが含まれます。
Wijmoコントロールを表すWijmo Webコンポーネントは、2つの基本クラスから2つの異なるバージョンのaddEventListenerメソッドを継承しています。wijmo.Controlクラスから独自バージョンのメソッドを継承し、基底のHTMLElementクラスからもこのメソッドを継承します。 このメソッドのこれら2つの実体は異なるシグネチャを持つため、Wijmo Webコンポーネントはそれらを区別してこのメソッドの適切な実装を呼び出すことができます。
次の例では、wjc-input-numberおよびwjc-linear-gaugeコンポーネントのvalue-changedイベントを使用して、それらの値を同期します。 wjc-flex-gridのformat-itemイベントを使用して、Active列のセル内容をカスタマイズすることもできます。
// InputNumber and LinearGauge synchronized using valueChanged event
let inpNumEvents = document.getElementById('inpNumEvents');
let gaugeEvents = document.getElementById('gaugeEvents');
inpNumEvents.addEventListener('value-changed', (e: CustomEvent) => {
// CustomEvent.target references the component where event occurred
gaugeEvents.value = (e.target).value;
});
gaugeEvents.addEventListener('value-changed', (e: CustomEvent) => {
inpNumEvents.value = (e.target).value;
});
// FlexGrid's Active column formatted using formatItem event
let gridEvents = document.getElementById('gridEvents');
gridEvents.itemsSource = dataSvc.getData(100);
gridEvents.addEventListener('format-item', (e: CustomEvent) => {
// CustomEvent.detail contains corresponding Wijmo event arguments
let args = e.detail,
grid = args.panel.grid;
if (args.panel === grid.cells &&
grid.columns[args.col].binding === 'active' &&
!args.range.equals(grid.editRange)) {
args.cell.innerHTML = grid.getCellData(args.row, args.col, false) ? 'Yes' : 'No';
}
});
WijmoのWebコンポーネント要素は、標準のDOM APIを使用して、ネイティブのHTML要素と同じように操作できます。 具体的には、次のことができます。
document.createElement('wjc-flex-grid')のように、document.createElementメソッドを使用してWijmoコンポーネントを作成します。
document.appendChild、document.insertBefore、document.removeChildなどのメソッドを使用して、DOMツリーの要素を追加、移動、削除します。
Wijmoの子コンポーネントでも同じことが言えます。たとえば、親のwjc-flex-gridでwjc-flex-grid-column要素を追加/削除/並べ替えることで、グリッド列を追加、削除、並べ替えることができます。
このサンプルは、対応するWijmo Webコンポーネントを作成し、それらをDOMツリーの適切な場所に追加することによって、列と列のフィルタを持つFlexGridをプログラムで作成します。
<label>FlexGrid with columns and filter created programmatically</label>
<div id="gridProg"></div>
// Find placeholder element
let placeHolder = document.getElementById('gridProg');
// Create FlexGrid web component
let gridProg = document.createElement('wjc-flex-grid');
// Add grid to DOM
placeHolder.appendChild(gridProg);
// Create Column web component
let countryCol = document.createElement('wjc-flex-grid-column');
// add child to parent before assigning its properties
gridProg.appendChild(countryCol);
countryCol.control.binding = 'country';
countryCol.control.header = 'Country';
countryCol.control.width = '*';
// Create Column web component
let downloadsCol = document.createElement('wjc-flex-grid-column');
// add child to parent before assigning its properties
gridProg.appendChild(downloadsCol);
downloadsCol.control.binding = 'downloads';
downloadsCol.control.header = 'Downloads';
// Create FlexGridFilter web component
let filter = document.createElement('wjc-flex-grid-filter');
// add child to parent before assigning its properties
gridProg.appendChild(filter);
filter.filterColumns = ['country'];
// Set grid data
(gridProg).itemsSource = dataSvc.getData(100);