はじめに
Wijmo(ウィジモ)は、グレープシティがHTML/JavaScript環境に向けて提供しているJavaScriptライブラリで、WebサイトやWebアプリケーションで活用できるUI部品を利用者に提供します。現状の最新版は「2021J v3」です。
Wijmoが提供するUI部品は、単体で利用する他に、Angular、React、Vue.jsといったJavaScriptライブラリ・フレームワークと組み合わせて利用することもできます。WijmoのUI部品は各環境でコンポーネントとしてシームレスに動作します。
本記事では、Wijmoが提供する高機能グリッド部品FlexGridを、Reactと組み合わせたクライアント側環境および、マイクロソフトが提供するASP.NET Coreのサーバー側環境と組み合わせた実装を紹介します。Visual Studio 2022のプロジェクトテンプレートをもとに実装して、React上でFlexGridを表示させます。また、ASP.NET CoreでWeb APIを実装して、戻り値をFlexGridで表示する方法も説明します。
対象読者
- UI部品としてWijmoの利用を検討されている方
- Reactで利用できるUI部品を試したい方
- ASP.NET CoreのWeb API実装について知りたい方
必要な環境
本記事のサンプルコードは、以下の環境で動作を確認しています。
- Windows 10 64bit版
- Wijmo 5.20213.824
- Microsoft Visual Studio Community 2022 17.0.5
- Node.js 16.13.2 64bit版
- Microsoft Edge 98.0.1108.43
サンプルコードに含まれるソリューションファイル(*.sln)をVisual Studio 2022で開くことで、ソースコードの確認や実行が行えます。
Visual StudioでReactプロジェクトを作る
WijmoをReactで使う準備として、まずVisual StudioでReactプロジェクトを作成して実行してみます。プロジェクトを実行して表示されるWebページ(図2)では、画面右上の「Counter」をクリックすると、ボタン押下でカウンターが増えるサンプルが表示されます。また「Fetch data」は、ASP.NET Coreで実装した天気予報のデータを模擬したWeb APIから取得したデータを表に表示するサンプルです。
プロジェクトの作成方法を説明します。まずVisual Studioでプロジェクトを新規作成します。プロジェクトテンプレートは「React.js での ASP.NET Core」を選択します。
プロジェクト名と生成先パスの設定を行った後、フレームワークの選択では「.NET 6.0」を選択し、それ以外はデフォルト設定のままで「作成」をクリックすると、図2の通り実行できるプロジェクトが生成されます。
Reactプロジェクトの概要説明
図2のプロジェクトをもとにFlexGridの実装を追加するため、プロジェクトを構成するファイル群の概要を解説します。ソリューションファイル(P001ReactPlain.sln)と同じ階層のP001ReactPlainフォルダー(図4)内で、ClientAppフォルダーがReactを利用したクライアント側のコード、それ以外がASP.NET Coreを利用したサーバー側のコードです。Web APIはControllers配下に配置します(記事後半でWeb APIを追加実装します)。
ClientAppフォルダー内(図5)には、Reactプロジェクトの定義ファイルpackage.jsonなどが存在します。aspnetcore-https.jsは開発用のSSL証明書を生成する処理のファイル、aspnetcore-react.jsは生成したSSL証明書を参照する設定ファイル(.env.development.local)を生成する処理のファイルです。publicフォルダーにはindex.htmlなどが配置されます。
Reactを利用した実装の実体は、ClientApp/srcフォルダー内(図6)に存在します。
最初に実行されるのがindex.jsで、それが内部的にApp.jsに定義されたAppコンポーネントをWebページに表示します。srcフォルダー内ファイルの役割を表1に示します。今回は、プロキシーを設定するsetupProxy.js(後述)以外は変更せずそのまま利用します。
No. | ファイル名 | 役割 |
---|---|---|
1 | App.js | Webページに表示する最上位のコンポーネント |
2 | App.test.js | App.jsの単体テストファイル |
3 | custom.css |
デフォルトのCSSファイル
|
4 | index.js |
最初に実行されて、App.jsのコンポーネントを画面に 表示する処理 |
5 | reportWebVitals.js | Webページの計測を行うWeb Vitalsのファイル |
6 | service-worker.js |
Webページと独立して動作するService Workerのファイル
|
7 | ServiceWorkerRegistration.js | Service Workerを登録する処理のファイル |
8 | setupProxy.js | プロキシーを設定する処理のファイル |
Webページの表示内容に対応する実装(コンポーネント)は、Clientapp/src/componentsフォルダー内に存在します(図7)。
componentsフォルダー内各ファイルの役割を表2に示します。Layout.jsがページ全体に対応し、その中にNavMenu.jsによる画面上部メニューが表示されます。画面上部メニューの「Home」「Counter」「Fetch data」リンクをクリックすると、各リンクに対応するHome.js、Counter.js、FetchData.jsのコンポーネントを切り替え表示できます。
No. | ファイル名 | 役割 |
---|---|---|
1 | Counter.js | Counterページに対応するコンポーネントファイル |
2 | FetchData.js | Fetch dataページに対応するコンポーネントファイル |
3 | Home.js |
Homeページに対応するコンポーネントファイル
|
4 | Layout.js | ページ全体の表示に対応するコンポーネントファイル |
5 | NavMenu.css | 画面上部メニューのスタイルシート |
6 | NavMenu.js | 画面上部メニューのコンポーネントファイル |
以上を踏まえて、本記事ではcomponentsフォルダーにコンポーネントのファイルを1つ追加して、その中でFlexGridを表示するように実装していきます。
サンプルコードと同じ天気予報をFlexGridで表示
以下ではFlexGridをReactで表示していきます。図8のサンプルでは、図2で通常の表を利用して表示していた天気予報をFlexGridで表示します。
実装方法を以下で説明します。まず、FlexGridのパッケージを追加するため、ClientAppフォルダーでリスト1のコマンドを実行します。「@grapecity/wijmo.react.grid」が、React対応のFlexGridパッケージです。
npm install @grapecity/wijmo.react.grid
次にcomponents配下に、追加するコンポーネントに対応するWijmoFlexGrid.jsを追加して、リスト2の通り実装します。
import { Component } from 'react'; // WijmoのCSS、FlexGridのコンポーネントをインポート ...(1) import '@grapecity/wijmo.styles/wijmo.css'; import { FlexGrid, FlexGridColumn } from '@grapecity/wijmo.react.grid'; // FlexGridを表示するコンポーネント ...(2) export class WijmoFlexGrid extends Component { // コンストラクター ...(3) constructor(props) { super(props); // stateの初期値を設定 ...(4) this.state = { forecasts: [], loading: true }; } // コンポーネント配置(マウント)時の処理 ...(5) componentDidMount() { // データを取得 ...(6) this.populateWeatherData(); } // コンポーネントを表示する処理 ...(7) render() { // 表示内容 ...(8) let content; // ロード中(state.loading == true)の場合 ...(9) if (this.state.loading) { content = <p><em>Loading...</em></p> } // ロード完了(state.loading == false)の場合 ...(10) else { content = // FlexGrid:グリッド全体を表す ...(11) <FlexGrid itemsSource={this.state.forecasts} isReadOnly={true}> {/*FlexGridColumn: グリッドの1列を表す ...(12)*/} <FlexGridColumn binding="date" header="日時" width={280} /> <FlexGridColumn binding="temperatureC" header="温度(摂氏)" width={120} /> <FlexGridColumn binding="temperatureF" header="温度(華氏)" width={120} /> <FlexGridColumn binding="summary" header="サマリー"></FlexGridColumn> </FlexGrid> } // 表示内容を返却 ...(13) return content; } // データを取得 ...(14) async populateWeatherData() { // weatherforecast APIからデータを取得 ...(15) const response = await fetch('weatherforecast'); // 取得データをJSONとして解釈 ...(16) const data = await response.json(); // 取得したデータと、ロード完了(loading = false)をstateに設定 ...(17) this.setState({ forecasts: data, loading: false }); } }
リスト2の内容を説明します。(1)でWijmoのCSSやFlexGridのコンポーネントをインポートします。コンポーネントの実装(2)では、まずコンストラクター(3)で、Reactで利用する内部状態(state)を初期設定します(4)。stateには、表示する天気予報の内容forecastsと、ロード中かどうかを表すloadingを含みます。
(5)のcomponentDidMountは、コンポーネントがページに配置(マウント)された時に実行されるReactのライフサイクルメソッドです。ここでは(6)の通り、後述するデータ取得処理を実行します。
(7)のrenderは、表示内容を返却すると画面に描画してくれるReactのメソッドです。まず(8)で、表示内容を表す変数contentを用意します。state.loadingを参照して、データがロード中の場合は(9)のロード中表示、ロード完了の場合は(10)のグリッド表示がcontentに代入されて、(13)で返却されます。この処理により、state.loadingが変更された時にReactがロード中とロード完了後の処理を自動的に切り替えます。
ロード完了後の表示(10)内にFlexGridを記述します。グリッド全体を表す<FlexGrid>コンポーネント(11)内に、グリッドの1列を表す<FlexGridColumn>コンポーネント(12)を列の数だけ配置します。<FlexGridColumn>コンポーネントでは、表示するデータ名をbindingに、ヘッダー文字列をheaderに、列の幅をwidthに、それぞれ指定します。
(6)で呼び出されるデータ取得メソッドpopulateWeatherData(14)では、ASP.NET Coreで実装されているweatherforecast Web APIからデータを取得(15)後、(16)の処理でデータをJSONとして解釈し、(17)でstateのforecastsにそのデータを設定するとともに、loadingにfalseを設定してロード完了を指定します。
リスト2のコンポーネントを表示するため、画面上部メニューに対応するNavMenu.jsにリンクを追加します(リスト3)。
<ul className="navbar-nav flex-grow"> (略) <NavItem><!-- 追加 --> <NavLink tag={Link} className="text-dark" to="/wijmo-flexgrid">Wijmo FlexGrid</NavLink> </NavItem> </ul>
さらに、App.jsのrenderメソッド内に定義されているルーティングの設定に、リスト2のコンポーネントに対応した記述を追加します(リスト4)。
render () { return ( <Layout> (略) <Route path='/wijmo-flexgrid' component={WijmoFlexGrid} /><!-- 追加 --> </Layout> ); }
以上の実装により、図8の通り、画面右上に追加されたリンクをクリックして、FlexGridで天気予報を表示するコンポーネントを画面表示できます。
[補足]Wijmoのライセンス設定
上記の実装だけでは、Wijmoはトライアル版として動作します。正式版にするには、ライセンスキーを設定するリスト5の実装をindex.jsに追加します。
// Wijmoのライセンス設定 import * as wjcCore from '@grapecity/wijmo'; wjcCore.setLicenseKey('<ライセンスキー>');
ASP.NET Coreで独自のAPIを作ってFlexGridに表示させる
図8の例では、Visual Studioが生成した天気予報のWeb APIを表示させてきましたが、以下では独自のAPIを実装してFlexGridで表示させる方法を説明します。図9のサンプルでは、CodeZineのWebページが提供しているRSSをサーバー側Web APIで読み込んでクライアント側に渡し、FlexGridで記事のタイトル・URL・公開日時を表示します。
まず、サーバー側でRSSを処理するため、NuGet パッケージ マネージャーでMicrosoft.SyndicationFeed.ReaderWriterパッケージを検索してインストールします。
次に、Controllers/RSSFetchController.csファイル(リスト6)を生成して、Web APIの処理を実装します。
[Route("api/[controller]")] [ApiController] public class RSSFetchController : ControllerBase { [HttpGet] public async Task<List<RSSElem>> GetAsync() { (後述) } }
クラスに付与した[Route("api/[controller]")]、[ApiController]属性により、「api/RSSFetch」というパスに対応するWeb APIであることを指定します。GetAsyncメソッドに付与された[HttpGet]属性は、HTTP GETでのアクセスで実行される処理であることを表します。GetAsyncメソッドの実装はリスト7の通りです。
(略:HttpClientでCodeZineのRSSを読み込んでXmlReaderを生成) // RSSを読み込むRssFeedReaderを生成 ...(1) var feedReader = new RssFeedReader(xmlReader); var elemList = new List<RSSElem>(); // RSSを読み込み ...(2) while (await feedReader.Read()) { switch (feedReader.ElementType) { // 読み込んだ項目がRSSのItemだった場合 ...(3) case SyndicationElementType.Item: // itemの内容を読み込んでRSSElemオブジェクトに代入し、リストに追加 var item = await feedReader.ReadItem(); var oneElem = new RSSElem() { Title = item.Title, Link = item.Links.First().Uri.ToString(), PubDate = item.Published.LocalDateTime }; elemList.Add(oneElem); break; } } // RSSElemリストを返却(JSONのAPI戻り値が生成される) ...(4) return elemList;
CodeZineのRSSをアクセスするHttpClientから、RSSをXMLとして読み込むXmlReaderクラスのオブジェクトxmlReaderを取得する処理の後、(1)でxmlReaderからRSSを読み込むRssFeedReaderを生成します。RSSの各要素をwhileループ(2)で読み込み、その要素タイプ(ElementType)がアイテム(SyndicationElementType.Item)だった場合(3)、そのタイトル、URL、公開日時をRSSElemクラス(クラス実装はサンプルコード参照)のオブジェクトに格納してリストに追加します。
最後に(4)で、RSSの全アイテムデータが格納されたリストを返却します。この処理で、ASP.NET Coreのフレームワークにより、リスト内容がJSON文字列に変換されてAPIの戻り値として返却されます。
Web APIの戻り値をFlexGridで画面に表示する処理は、<FlexGridColumn>に指定する列名が異なる程度で、ほぼリスト2と同一です。詳細はサンプルコードを参照してください。
[補足]Reactプロジェクトのプロキシー設定
Visual Studio 2022のReactプロジェクトを開発環境で実行すると、Reactで実装したWebページをホストするNode.jsのWebサーバーと、Web APIをホストするASP.NET CoreのWebサーバーが同時に動作します。これらのサーバーはオリジン(ホスト名+ポート番号)が異なるため、いわゆる同一オリジンポリシーにより、Node.jsのWebサーバーから取得したWebページがASP.NET CoreのWebサーバーが提供するWeb APIへアクセスできません。
そのため、Visual Studio 2022のReactプロジェクトでは、Node.jsのWebサーバーがASP.NET CoreのWebサーバーのプロキシーとなって、Web APIへのアクセスを中継する設定が行われます。設定を行うのは表1、No.8のsetupProxy.jsで、中継するURLのパスをファイルに記述します(リスト8)。
const context = [ "/weatherforecast", "/api" // プロキシーが/api配下を中継するように設定 ...(1) ];
リスト6のWeb APIは「api/RSSFetch」というパスでアクセスされるため、プロキシーが中継対象にするパスを(1)の通り追加する必要があります。(1)の記述により「/api」配下の任意のパスが中継対象となります。
まとめ
本記事では、Visual Studio 2022のReactテンプレートで生成されたReactのWebページに、グレープシティのUI部品Wijmoに含まれるグリッド部品FlexGridを利用する方法を説明しました。FlexGridは、Reactのコンポーネントとして定義されるため、React本体とシームレスに利用できます。ASP.NET CoreのWeb APIと組み合わせる方法も説明しました。