Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

注目JavaScriptライブラリReactで「Wijmo(ウィジモ) 5」を使いこなす

ECMAScript 5に準拠した高速・軽量なJavaScript UIライブラリ「Wijmo 5」の活用 第14回

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

 本連載では、グレープシティが提供するJavaScriptライブラリWijmo(ウィジモ)について、サンプルとともに利用例を紹介します。今回は、最近注目のJavaScriptライブラリReactと組み合わせて、Wijmoを利用する方法を紹介します。Reactの環境では、WijmoのコントロールをReactのコンポーネントとして利用できます。

はじめに

 Wijmo(ウィジモ)は、グレープシティがHTML/JavaScript環境に向けて提供しているJavaScriptライブラリで、WebサイトやWebアプリケーションで活用できるUI部品を利用者に提供します。現行版はECMAScript 5に対応した「Wijmo 5」です。

 Wijmoは単体での利用に加え、さまざまなJavaScriptフレームワークやライブラリと組み合わせて利用できます。本連載で主に紹介してきたAngularのほか、ReactVue.jsKnockoutをサポートします。今回は、最近注目が高まっているReactでWijmoを利用する方法を紹介します。

対象読者

  • WebサイトやWebアプリケーションのレベルをワンランク上げたい方
  • AngularでWijmoを使っていて、最近話題のReactも試したい方
  • 高度なUI部品を手軽に使いたいReactユーザーの方

必要な環境

 Wijmo 5はECMAScript 5に対応するブラウザーをサポートします。詳細はWijmoのWebサイトで案内されています。

 Reactでは、プロジェクトを生成する「create-react-app」ツールが利用できます。ツールの動作にはNode.jsが必要です。

 以上を踏まえて、今回は以下の環境で動作を確認しています。

  • Windows 10 64bit版
    • Wijmo 5 5.20182.524
    • React 16.5.2
    • Node.js v8.12.0 64bit版
    • Microsoft Edge 42.17134.1.0

 サンプルコードを実行するには、プロジェクトのフォルダーで「npm install」コマンドを実行してライブラリをダウンロード後、「npm start」コマンドを実行します。

Reactとは

 Reactは、Facebook社とオープンソースコミュニティで開発されているJavaScriptライブラリで、以下の特徴があります。

Viewのみを担当

 Reactは画面のユーザーインターフェース(View)作成にフォーカスしたライブラリで、それ以外の機能を提供する任意のライブラリと組み合わせて利用できます。

仮想DOM

 Webページ要素のツリー構造をメモリー上で操作して、最小限の差分だけを実際のWebページ(DOMツリー)に反映する仕組みで、高速な動作を実現します。

単一方向のデータフロー

 Reactでは、保持しているデータを画面に反映する一方で、画面の変更を自動的にデータに反映する機能(いわゆる「双方向データバインディング」)は提供しません。データの流れを単一方向にすることで、わかりやすいコードを実現します。

 Reactの詳細については、CodeZineの連載記事「基礎からはじめるReact入門」も参考にしてください。

Reactプロジェクトを生成して内容を確認

 ReactでWijmoを利用する前準備として、ここでは、create-react-appツールで生成するReactのプロジェクトについて説明します。Node.jsがインストールされている環境で、リスト1の通りコマンドを実行すると、Reactのプロジェクトを生成して実行できます。(1)のnpxは、create-react-appをインストールせずに、直接実行できるコマンドです。

[リスト1]Reactのプロジェクトを生成して実行するコマンド
npx create-react-app p001-default # プロジェクト生成 ...(1)
cd p001-default                   # プロジェクトフォルダーに移動 ...(2)
npm start                         # プロジェクト実行 ...(3)

 リスト1(3)を実行するとWebブラウザーが起動して、図1のように表示されます。

図1 create-react-appで生成したプロジェクトの実行結果(p001-default)
図1 create-react-appで生成したプロジェクトの実行結果(p001-default)

 本記事では、リスト1のコマンドで生成したReactプロジェクトを修正して、WijmoのコントロールをReactプロジェクトで表示させています。Reactプロジェクト構成の詳細については、CodeZineのReact記事も参考にしてください。

ReactプロジェクトにWijmoを追加して動作させる

 ReactプロジェクトでWijmoを利用できるようにするには、リスト2のコマンドを実行します。Node.jsのパッケージマネージャーnpmを利用して、プロジェクトにWijmoを追加できます。

[リスト2]プロジェクトにWijmoを追加するコマンド
npm install --save wijmo

 プロジェクトに追加したWijmoの利用方法を、図2のサンプルで説明します。このサンプルでは、Wijmoのゲージコントロール(LinearGauge)と、ゲージの値を設定するテキストボックスを画面に表示します。マウスやタッチでゲージを操作すると、テキストボックスの数値が更新されます。逆に、テキストボックスの数値を変更すると、ゲージが更新されます。

図2 ReactプロジェクトでWijmoのゲージを表示するサンプル(p002-basic)
図2 ReactプロジェクトでWijmoのゲージを表示するサンプル(p002-basic)

 最初に、画面表示に対応するAppコンポーネント(App.js)にリスト3の通り記述して、Wijmoのファイルやモジュールをインポートします。(1)はWijmoのCSS、(2)は日本語リソースです。(3)は、このサンプルで利用するゲージ機能を含むWijmoのモジュール(wijmo.react.gauge)を「wjGauge」という名前でインポートする記述です。

[リスト3]Wijmoのファイルやモジュールをインポートする記述(p002-basic/src/App.js)
import 'wijmo/styles/wijmo.css'; // CSS ...(1)
import 'wijmo/cultures/wijmo.culture.ja'; // 日本語リソース ...(2)
import * as wjGauge from 'wijmo/wijmo.react.gauge'; // Wijmoモジュール ...(3)

 次に、Appクラスを、リスト4の通り実装します。

[リスト4]Appクラスの実装(p002-basic/src/App.js)
class App extends Component {
  // コンストラクター // ...(1)
  constructor(props) {
    // スーパークラスのコンストラクターでpropsを初期設定 // ...(2)
    super(props);
    // stateを初期設定 ...(3)
    this.state = {
      gaugeValue: 30
    }
    // メソッドをthisにバインド ... (4)
    this.gaugeChanged = this.gaugeChanged.bind(this);
    this.textboxChanged = this.textboxChanged.bind(this);
  }
  // コンポーネントの表示 ...(5)
  render() {
    return (
      <div className="App">
        <h1>Wijmo + React(ゲージ)</h1>
        {/* WijmoのLinearGauge ...(6) */}
        <wjGauge.LinearGauge className="wijmo-control" isReadOnly={false}
         value={this.state.gaugeValue} valueChanged={this.gaugeChanged}/>
        {/* ゲージの値を表示・設定するテキストボックス ...(7)*/}
        ゲージの値:<input type="text" className="textbox"
         value={this.state.gaugeValue} onChange={this.textboxChanged}/>
      </div>
    );
  }
  // ゲージが変更されたときの処理 ...(8)
  gaugeChanged(newValue) {
    this.setState({gaugeValue: newValue.value});
  }
  // テキストボックスが変更されたときの処理 ...(9)
  textboxChanged(newValue) {
    this.setState({gaugeValue: Number(newValue.target.value)});
  }
}

 (1)はクラスのコンストラクターです。Reactのコンポーネントでは、コンストラクターの引数で渡される情報のオブジェクト(props)を、スーパークラスのコンストラクターで(2)のように初期設定します。また、Reactコンポーネントの内部状態を管理するthis.stateプロパティを、(3)で初期設定します。ここではゲージ値の初期値30をgaugeValueに設定します。(4)は、後述するイベント処理内で、Appクラス自身をthisとして参照できるようにする処理です。

 (5)のrenderは、コンポーネントを表示するReactのメソッドで、HTMLタグによく似た記法でコンポーネントの表示内容を記述できます。この記法はJSXと呼ばれるJavaScript拡張記法です。

 (6)がWijmoのゲージ(LinearGauge)に対応する記述で、表1の属性を設定します。「value={this.state.gaugeValue}」のようにタグの属性値を{}で囲むのはReactの記法で、JavaScriptの変数やメソッドを設定できます。

表1 LinearGaugeに設定する属性
属性名 属性の意味 設定内容
isReadOnly 読み取り専用かどうか false(操作可能)
value ゲージの値 this.state.gaugeValue(stateに保持した値)
valueChanged ゲージ変更時の処理 リスト4(8)のthis.gaugeChangedメソッド

 同様に、テキストボックスに対応する記述(7)には、表2の属性を設定します。

表2 テキストボックスに設定する属性
属性名 属性の意味 設定内容
value テキストボックスの値 this.state.gaugeValue(stateに保持した値)
onChange テキストボックス変更時の処理 リスト4(9)のthis.textboxChangedメソッド

 ゲージの変更時は(8)、テキストボックスの変更時は(9)の処理が実行されます。引数から変更後の値を取得して、this.setStateメソッドでstateのgaugeValueを更新しています。this.setStateは、stateを更新するReactのメソッドで、更新内容は画面に自動的に反映されます。

[注]単一方向のデータフロー

 Reactでは、データフローが単一方向のため、画面が更新されても自動的に内部状態(state)が更新されません。画面が更新された場合、リスト4(8)(9)のようにthis.setStateメソッドで明示的にstateを更新する必要があります。

 対してAngularでは、双方向データバインディング機能で、画面と内部状態を双方向に同期します。図2と類似のサンプルをAngularで実装した本連載の過去記事も参照してください。

グリッド部品FlexGridとチャート部品FlexChartを試す

 WijmoのFlexGridはExcelのようなグリッドを表示する部品、FlexChartはさまざまなチャートを表示する部品です。これらの利用例を、図3のサンプルで説明します。グリッドの内容を変更すると、連動してチャートに反映されます。

図3 FlexGridとFlexChartを組み合わせたサンプル(p003-chart-grid)
図3 FlexGridとFlexChartを組み合わせたサンプル(p003-chart-grid)

 まず、利用するWijmoのモジュールを、リスト5の通りインポートします。(1)はFlexGrid、(2)はFlexChartに対応します。(3)はWijmo本体のモジュールで、FlexGridやFlexChartに表示するデータを管理するCollectionViewクラスが含まれます。

[リスト5]図3のサンプルでインポートするモジュール(p003-chart-grid/src/App.js)
import * as wjGrid from 'wijmo/wijmo.react.grid'; // FlexGrid ...(1)
import * as wjChart from 'wijmo/wijmo.react.chart'; // FlexChart ...(2)
import * as wj from 'wijmo/wijmo'; // Wijmo本体(CollectionView) ...(3)

 Appクラスのコンストラクターでは、FlexGridとFlexChartで共有するデータをstateに設定します。ここでは、ym(年月)/time(稼働時間)/count(生産数)のデータを持つJavaScriptオブジェクトの配列をコンストラクターに与えてCollectionViewを生成し、cvDataとしてstateに設定します。

[リスト6]this.stateにデータを設定する実装(p003-chart-grid/src/App.js)
this.state = {
  cvData: new wj.CollectionView([
    {
      'ym': '2018/9',
      'time': 160,
      'count': 200
    },
(略)
  ])
};

 renderメソッドで、画面に表示するFlexGridとFlexChartを記述します。FlexGridの記述はリスト7です。

[リスト7]FlexGridの記述(p003-chart-grid/src/App.js)
<wjGrid.FlexGrid itemsSource={this.state.cvData}> ...(1)
  <wjGrid.FlexGridColumn header="年月" binding="ym" width="*"/> ...(2)
  <wjGrid.FlexGridColumn header="稼働時間" binding="time" width="*"/> ...(3)
  <wjGrid.FlexGridColumn header="生産数" binding="count" width="*"/> ...(4)
</wjGrid.FlexGrid>

 (1)のFlexGridタグがグリッドの本体で、表示するデータ(this.state.cvData)をitemsSource属性に設定します。(2)~(4)のFlexGridColumnタグはグリッドの列で、binding属性でym(年月)、time(稼働時間)、count(生産数)をそれぞれ表示するようにします。「width="*"」は、列を可能な限り広げて表示する設定です。

 FlexChartはリスト8の通り記述します。

[リスト8]FlexChartの記述(p003-chart-grid/src/App.js)
<wjChart.FlexChart itemsSource={this.state.cvData} bindingX="ym"> ...(1)
  <wjChart.FlexChartSeries name="稼働時間" binding="time"/> ...(2)
  <wjChart.FlexChartSeries name="生産数" binding="count"
   chartType="LineSymbols"/> ...(3)
  <wjChart.FlexChartLegend position="Bottom"/> ...(4)
</wjChart.FlexChart>

 (1)のFlexChartタグがチャートの本体で、itemsSource属性にはリスト7同様に表示データを設定します。bindingX属性はチャートのx軸設定で、ここではym(年月)をx軸に設定します。(2)と(3)のFlexChartSeriesタグはグラフのデータ系列で、それぞれのbinding属性で(2)にtime(稼働時間)、(3)にcount(生産数)を表示するよう設定します。(3)ではグラフ種類を表すchartType属性にLineSymbols(線グラフ)を設定します。chartType属性を指定しない(2)のデータ系列は棒グラフになります。(4)のFlexChartLegendタグは凡例で、position属性で表示位置をBottom(下部)に設定します。

CollectionViewを利用したデータ同期と画面の更新

 リスト5~8のサンプル(p003-chart-grid)には、リスト3~4のサンプル(p002-basic)のように、画面更新時にstateを更新する実装がありませんが、FlexGridの変更がFlexChartに反映されます。これはCollectionViewの機能によるもので、CollectionViewを共有するWijmoコントロール間では、データが自動的に同期されて画面に反映されます。

 一方、Wijmoコントロール以外の画面要素とデータを共有する場合は、stateを更新して画面に反映するReactの方法に従う必要があります。このような実装方法を、FlexGridの内容をHTMLのtableタグで表示する図4のサンプルで説明します。

図4 FlexGridの内容をテーブルに表示するサンプル(p004-table-grid)
図4 FlexGridの内容をテーブルに表示するサンプル(p004-table-grid)

 FlexGridの記述はリスト7と同様です。データを表示するテーブルは、リスト9の通り記述します。(1)でCollectionView(this.state.cvData)のitemsプロパティでデータを取得して、mapメソッドで各行を<tr>タグ、<td>タグとして出力します。

[リスト9]テーブルの記述(p004-grid-table/src/App.js)
<table className="disp-table">
  <th>年月</th>
  <th>稼働時間</th>
  <th>生産数</th>
  {
    // CollectionViewのデータを出力 ...(1)
    this.state.cvData.items.map((value, index, array) => {
      return(
      <tr>
        <td>{value.ym}</td>
        <td>{value.time}</td>
        <td>{value.count}</td>
      </tr>)
    })
  }
</table>

 このままではCollectionViewの変更がテーブルに反映されないので、CollectionViewが変更されたときに発生するonCollectionChangedイベントの処理を、リスト10の通り実装します。this.setStateメソッドでCollectionViewを再設定すると、Reactの内部処理でテーブルが再描画されます。

[リスト10]CollectionViewが変更されたときの処理(p004-grid-table/src/App.js)
this.state.cvData.onCollectionChanged = (() => {
  this.setState({cvData: this.state.cvData});
});

[注]ライセンスの設定

 npmでインストールしたWijmoは正式版ですが、ライセンスキーを設定しないとトライアル版として動作し、画面上にトライアル版である旨が表示されます。公式ページの手順で取得したライセンスキーを、リスト11のようにsetLicenseKeyメソッドで設定すると、Wijmoが正式版として動作するようになり、トライアル版の表示が消えます。

[リスト11]ライセンスキーの設定方法
import * as wj from 'wijmo/wijmo';
wj.setLicenseKey('<ここにライセンスキーを設定>');

まとめ

 本記事では、グレープシティのJavaScriptライブラリWijmo 5を、Reactと組み合わせて利用する方法を説明しました。ReactプロジェクトにWijmoを組み込むことで、WijmoのコントロールをReactのコンポーネントとしてシームレスに活用できます。

参考資料

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • WINGSプロジェクト  吉川 英一(ヨシカワ エイイチ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XMLD...

All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5