メシウスのWebサイトではJavaScriptライブラリを活用した業務アプリのUIの実装サンプルを、ダウンロード可能なソースコード付きで多数公開しています。
本連載ではWebサイトで公開しているサンプルアプリケーションを例に、さまざまな業務アプリケーションのUIの実装のポイントや、コントロールの選定ポイントを解説していきます。
第5回となる本記事では、JavaScript UIライブラリ「Wijmo(ウィジモ)」の各種コントロールを使用してマーケティング施策の効果を分析する「キャンペーン分析ダッシュボード(BIツール風)」デモについて解説します。マーケティング施策に限らず、業務向けの分析画面を構築する例となっておりますので、ぜひご活用ください。

利用しているコントロール
キャンペーン分析ダッシュボード(BIツール風)デモでは、主に以下のWijmoコントロールを使用しています。
| コントロール名 | 利用目的 | イメージ |
|---|---|---|
| ComboBox | キャンペーン、サービス、期間を絞り込む | ![]() |
| TabPanel | 各タブを切り替える | ![]() |
| FlexChart | 各種データの可視化(面、折れ線、バブル、グルーピングなど) | ![]() |
![]() |
||
![]() |
||
![]() |
||
| FlexGrid | 各種データの可視化 | ![]() |
![]() |
||
![]() |
実装のポイント
ここからは、本デモで実現している機能の中から、実装のポイントとなるものを3つピックアップし、ソースコードを交えながら解説します。
なお、本デモはJavaScriptフレームワーク「React」を使用して実装されています。
レーティングの実装
1番上のタブの「登録実績」画面にある「拠点別顧客変換率」のグリッドでは、各拠点の評価を星印(★)で表示しています(レーティング)。

本デモの実装では、Wijmoが提供しているCellMakerクラスを利用して、セルにレーティングを設定しています(CellMakerを使ったレーティングの使用方法については「グリッド:レーティングセル」デモもご活用ください)。
const conversionGridInit = useCallback((grid) => {
・・・途中省略・・・
const c2 = new Column();
c2.binding = 'estrellas';
c2.header = '評価';
c2.width = 200;
c2.align = 'center';
//CellMakerクラスでレーティングを設定
c2.cellTemplate = CellMaker.makeRating({
range: [1, 5],
label: ''
});
・・・
}, []);なお、同様の見た目を実現する他の方法として、「スパークライン」デモのようにformatItemイベントを利用して直接セル要素に星印を設定する方法もありますが、CellMakerクラスを利用する方が実装コードを簡素化できるのにくわえて、パフォーマンス面でも有利です。
var theGrid = new wjGrid.FlexGrid('#theGrid', {
・・・
formatItem: function (s, e) {
if (e.panel == s.cells) {
var item = s.rows[e.row].dataItem;
switch (s.columns[e.col].binding) {
case 'rating':
formatRatingCell(e.cell, item.rating);
break;
・・・
}
}
}
});
・・・
function formatRatingCell(cell, rating) {
var html = '<div aria-label="レーティング:星' + rating + ' 個">';
for (var i = 0; i < rating; i++) {
html += '<span class="glyphicon glyphicon-star"></span>';
}
html += '</div>';
cell.innerHTML = html;
}グルーピングされた棒チャート
3番目のタブの「商談パイプライン」画面にある「地域・担当会社別提案数」の棒チャートでは、Y軸の項目を地域でグルーピングして表示しています。

軸の項目をグルーピングするには、軸のgroupsOptionsプロパティで表示方法を設定するとともに、FlexChartのデータソースにCollectionViewを設定し、そのCollectionViewのgroupDescriptionsプロパティでグループ化の条件を定義します(軸グループの使用方法については「チャート:軸グループ」デモもご活用ください)。
//データソースの設定部分
if (!tab3CityView.current) {
tab3CityView.current = new CollectionView([]);
const cityGroup = new PropertyGroupDescription('city');
tab3CityView.current.groupDescriptions.push(cityGroup);
}
・・・テンプレート部分・・・
{/* 右: 地域・担当会社別 AxisGroups 横棒チャート */}
<div className="bi-panel bi-tab3-city-panel">
<div className="bi-panel-title">地域・担当会社別提案数</div>
<wjChart.FlexChart
className="bi-tab3-city-chart"
itemsSource={tab3CityView.current}
bindingX="company" chartType="Bar"
legend={{ position: Position.None }}
palette={['#4a72c4']}
initialized={(chart) => {
chart.axisY.groupsOptions = { display: AxisGroupsDisplay.Show };
chart.axisX.axisLine = true;
chart.axisX.min = 0;
if (tab3CityView.current)
tab3CityView.current.sourceCollection = tab3Data.cityCompanyData;
}}>
<wjChart.FlexChartSeries binding="value" name="件数" />
</wjChart.FlexChart>
</div>CollectionViewというとFlexGridのデータソースとして利用するイメージが強いですが、このようにFlexChartでも活用することができます。
セルの書式設定
通常、グリッドのセルに書式を設定したい場合、Columnクラスのformatプロパティを利用して、列単位で書式を設定するのが一般的です。
たとえば、一番下のタブの「顧客セグメント分析」画面にある「セグメント別指標サマリ」のグリッドではこの方法を使用しています。

const defs = [
{ binding: 'name', header: 'セグメント', width: 150 },
{ binding: 'count', header: '登録件数', width: 110, align: 'right', format: 'n0' },
{ binding: 'ratioPct', header: '構成比 %', width: 100, align: 'right', format: 'p0' },
{ binding: 'convRate', header: '転換率 %', width: 100, align: 'right', format: 'p0' },
・・・
];
defs.forEach(({ binding, header, width, align, format }) => {
const c = new Column();
・・・
if (format)
c.format = format;
grid.columns.push(c);
});一方で、4番目のタブの「ROI・収益分析」画面にある「インプット」「アウトプット(算出値)」のグリッドのように、各行に応じて書式を設定したいケースもあります。

このような表示を実現するには、セル毎に表示内容や動作をカスタマイズできるformatItemイベントを利用する方法が考えられます(formatItemの使用方法については「グリッド:条件付き書式」デモもご活用ください)。
本デモでは、グリッドの行に対応するデータに書式を判断するプロパティ(fmt)を事前に設定しておき、formatItemイベント内でセルが描画される際に、セルに対応するアイテムのfmtプロパティを参照して、それに応じた書式をテキストに適用しています。
//データソース設定
const row = (label, fmt, keyName, total) => ({
label, fmt,
campA: v('春季新規獲得', keyName),
campB: v('夏季ファン層拡大', keyName),
campC: v('秋冬リテンション', keyName),
total,
});
const inputRows = [
row('イニシャティブコストの合計', 'currency', 'cost', totCost),
row('ターゲットオーディエンス(人)', 'number', 'audience', sum('audience')),
row('転化率(リード生成率)%', 'percent', 'leadRate', null),
row('コンバージョン率(購入率)%', 'percent', 'convRate', null),
row('1販売あたりの平均収益', 'currency', 'revPerSale', totRevPS),
row('1販売あたりの平均利益', 'currency', 'profitPerSale', totProfPS),
];//formatItemイベントの処理
const formatRoiItem = useCallback((sender, e) => {
var _a, _b;
if (e.panel.cellType !== 1)
return;
const item = (_a = e.panel.rows[e.row]) === null || _a === void 0 ? void 0 : _a.dataItem;
・・・
//fmtからテキストに設定する文字列を判断する
switch (item.fmt) {
case 'currency':
e.cell.textContent = val === 0 ? '-' : '¥' + val.toLocaleString('ja-JP', { minimumFractionDigits: 0, maximumFractionDigits: 2 });
break;
case 'percent':
e.cell.textContent = val === 0 ? '-' : val.toFixed(2) + ' %';
break;
case 'number':
e.cell.textContent = val.toLocaleString('ja-JP');
break;
default: break;
}
}, []);さいごに
今回はWijmoの各種コントロールを使用した「キャンペーン分析ダッシュボード(BIツール風)」デモの実装ポイントを解説しました。
製品サイトでは今回ご紹介したデモアプリケーションをブラウザ上で手軽にお試し可能で、加えてソースコード付きでダウンロードも可能なので、是非こちらもチェックしてみてください。
そのほか、製品サイトでは、Wijmoのトライアル版も公開しておりますので、こちらもご確認ください。
また、ご導入前の製品に関するご相談、ご導入後の各種サービスに関するご質問など、お気軽にお問合せください。









