Wijmo

Web Components入門

このページは、Wijmo WebComponentsを使い始める方法を示しています。

はじめに

このサンプルでは、Wijmo WebComponentsのベータ版を紹介します。 Wijmo WebComponentsを使用すると、WijmoコントロールのカスタムタグをHTMLページに追加し、追加のフレームワークを使用せずに通常のDOMエレメントとして操作できます。 WebComponents標準を完全にサポートしていないブラウザーでは、いくつかの追加のポリフィルが必要になる場合があります。

WebComponentsに精通していない場合は、技術紹介情報を参照してください。

Wijmo WebComponentsの現在の実装状態は次の通りです。

  1. Wijmoコントロールを表すトップレベルのWebコンポーネント(例:FlexGridコントロールを表すwjc-flex-gridコンポーネント)は、対応するコントロールクラスから継承されます。 たとえば、WjcFlexGridコンポーネントクラスはFlexGridコントロールクラスを継承します。

    これは、WijmoがWebComponentsモードで使用されている場合、WijmoのControl基本クラスがHTMLElementクラスを拡張することを意味します。

  2. FlexGridカラムを定義するwjc-flex-grid-columnコンポーネントのような最上位コンポーネントを補完する子コンポーネントは、それらが表すWijmoクラスの上にラッパーとして機能します。 子コンポーネントはHTMLElementクラスから直接継承され、基になるWijmoクラスインスタンスはコンポーネントの特別なcontrolプロパティを介してアクセスできます。
  3. Wijmoクラスのプロパティは、コンポーネント要素の属性を使用して定義できます。 属性値が変更されると、対応するWijmoクラスプロパティがそれに応じて更新されます。 クラスプロパティの値を変更しても、対応する属性値は変更されません。 これは将来変更される可能性がありますが、今必要かどうかについては決定していません。
  4. JavaScriptコードは、ネイティブのElement.addEventListener('event', handler)メソッドを使用してWijmoコントロールイベントにハンドラを登録できます。
  5. Wijmoコンポーネントは現在Shadow DOMを使用していません。 これは将来のバージョンで対応予定です。 ここでの課題の1つは、WijmoがCSSを使用してコントロールのパーツを詳細にカスタマイズできることですが、一方でShadow DOMの目的はそれを防ぐことです。 この制限を緩和することができるShadow DOM仕様の新しい提案があります。 私たちはその変更を追跡し続けています。 現時点では、Wijmo Webコンポーネントとその部品は、グローバルCSSを使用して、通常のWijmoコントロールと同じ方法でカスタマイズできます。

Wijmo Webコンポーネント相互運用モジュールを使用すると、次の例に示すように、HTMLマークアップにコントロールのタグを追加できます。

HTML
<label>InputNumber</label> <wjc-input-number value="5" step="3"></wjc-input-number> <label>フィルタと列を含むFlexGrid</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>
JS
let gridIntro = document.getElementById('gridIntro'); gridIntro.itemsSource = dataSvc.getData(100);

結果 (ライブ):

設定

このサンプルはnpmモジュールに基づいており、SystemJSランタイムモジュールローダーまたはWebpackバンドラーを使用して実行するように構成されています。

WebComponentsベースのアプリケーション構成の重要な側面は次のとおりです。

  1. コマンドプロンプトでWijmoをインストールします。
    > npm install wijmo --save
  2. 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>
  3. ルートHTMLページで次の設定を行い、WijmoのWebComponentsモードを有効にします。これはWijmoモジュールが読み込まれる前に実行する必要があります。
    <script>
        window['wj-control-is-element'] = true;
    </script>

    この割り当てによって、WijmoのControlクラスは、通常のようにObjectクラスではなく、HTMLElementクラスを拡張します。

  4. Wijmo WebComponentsの必要なモジュールをES6/TypeScriptコードでインポートします。
    import 'wijmo/wijmo.webcomponents.input';
    import 'wijmo/wijmo.webcomponents.grid';

    これらのインポートによって、モジュールはwindow.customElements.define()メソッドを使用してWebコンポーネントをグローバルに登録します。

  5. (注:このサンプルには該当しません) 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コンポーネントをアプリケーションで使用できます。

HTML
<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>
JS
import 'wijmo/wijmo.webcomponents.input';

結果 (ライブ):

属性

プロパティ値は、Wijmo Webコンポーネント要素の対応する属性を使用して指定できます。

次のルールを考慮する必要があります。

  1. 属性名はダッシュ区切り形式で指定する必要があります。例えば、firstDayOfWeekプロパティの値はfirst-week-week属性で指定します。
  2. 単純な型のプロパティだけを属性として指定できます。 列挙型のプロパティの場合は、selection-mode="Day"のように列挙型メンバー名を使用できます。
  3. 属性値は常に文字列であるため、Wijmo Webコンポーネントは対応するプロパティに値を割り当てる前に適切な値の変換を行います。

次の例は、異なる型のプロパティが指定されたwjc-calendarWebコンポーネントを示しています。

HTML
<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>
JS
import 'wijmo/wijmo.webcomponents.input';

結果 (ライブ):

子コンポーネント

Wijmo Controlsを表すトップレベルのWebコンポーネントに加えて、親コンポーネントの設定をタグでカスタマイズするのに役立つ子コンポーネントもあります。 たとえば、wjc-flex-grid-columnコンポーネントを使用してFlexGrid列のリストを指定したり、wjc-flex-chart-series子コンポーネントを使用してFlexChartシリーズを定義できます。

子コンポーネントは親コンポーネントの直接の子でなければなりません。

以下に例を示します。

  1. wjc-flex-gridコンポーネントには、グリッド列のリストを定義するwjc-flex-grid-column子コンポーネントと、グリッドに列フィルタを適用するwjc-flex-grid-filter子コンポーネントが含まれます。
  2. wjc-flex-chartコンポーネントには、チャートのシリーズを定義するwjc-flex-chart-series子コンポーネントと、チャートのX軸とY軸をカスタマイズするwjc-flex-chart-axisコンポーネントが含まれます。
HTML
<label>列とフィルタを含むFlexGrid</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</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>
JS
let chData = dataSvc.getData(dataSvc.countries.length); let gridWithChildren = document.getElementById('gridWithChildren'); gridWithChildren.itemsSource = chData; let chartWithChildren = document.getElementById('chartWithChildren'); chartWithChildren.itemsSource = chData;

結果 (ライブ):

コード内での参照と使用

document.getElementByIdメソッドのような従来のDOM APIを使用して、Wijmo Webコンポーネント要素を取得することができます。 その後、次のルールに従って、この要素のWijmo固有のAPIにアクセスできます。

  1. Wijmoコントロールを表す最上位レベルのコンポーネントの場合、対応するコントロールクラスから直接継承されるため、すべてのコントロールのAPIは要素のすぐ下にあります。 たとえば、次のコードを使用してFlexGrid Webコンポーネントにデータを割り当てることができます。
    document.querySelector('wjc-flex-grid').itemsSource = getData();
  2. 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コンポーネントにフィルタ列リストを定義します。

HTML
<label>グループパネルとフィルタを含むFlexGrid</label> <wjc-group-panel id="panelRef" placeholder="ここに列をドラッグしてください。"> </wjc-group-panel> <wjc-flex-grid id="gridRef"> <wjc-flex-grid-filter id="filterRef"></wjc-flex-grid-filter> </wjc-flex-grid>
JS
// 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つの主要なプロパティがあります。

  1. target - イベントをトリガーしたWebコンポーネントを参照します。
  2. 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-gridformat-itemイベントを使用して、Active列のセル内容をカスタマイズすることもできます。

HTML
<label>valueChangedイベントを使用してInputNumberとLinearGaugeを同期する</label> <wjc-input-number id="inpNumEvents" value="30" step="10" min="0" max="100"> </wjc-input-number> <wjc-linear-gauge id="gaugeEvents" value="30" step="10" min="0" max="100" is-read-only="false" is-animated="false" thumb-size="10" style="display:block;height:30px"> <wjc-range wj-property="face" thickness="0.25"></wjc-range> <wjc-range wj-property="pointer" thickness="0.25"></wjc-range> </wjc-linear-gauge> <label>FlexGridのActive列をformatItemイベントを使用して表示する</label> <wjc-flex-grid id="gridEvents"> <wjc-flex-grid-column binding="country" header="Country" width="*"> </wjc-flex-grid-column> <wjc-flex-grid-column binding="downloads" header="Downloads"> </wjc-flex-grid-column> <wjc-flex-grid-column binding="active" header="Active"> </wjc-flex-grid-column> </wjc-flex-grid>
JS
// valueChangedイベントを使用してInputNumberとLinearGaugeを同期する 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のActive列をformatItemイベントを使用して表示する 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要素と同じように操作できます。 具体的には、次のことができます。

  1. document.createElement('wjc-flex-grid')のように、document.createElementメソッドを使用してWijmoコンポーネントを作成します。
  2. document.appendChilddocument.insertBeforedocument.removeChildなどのメソッドを使用して、DOMツリーの要素を追加、移動、削除します。
  3. Wijmoの子コンポーネントでも同じことが言えます。たとえば、親のwjc-flex-gridwjc-flex-grid-column要素を追加/削除/並べ替えることで、グリッド列を追加、削除、並べ替えることができます。

このサンプルは、対応するWijmo Webコンポーネントを作成し、それらをDOMツリーの適切な場所に追加することによって、列と列のフィルタを持つFlexGridをプログラムで作成します。

HTML
<label>プログラムで作成された列とフィルタを含むFlexGrid</label> <div id="gridProg"></div>
JS
// 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);

結果 (ライブ):