Web AppBuilderカスタムウィジェット(4) 管理者向けに設定画面を追加する

ウィジェットの独自設定を行う画面を作成します。

Web AppBuilder for ArcGIS(Developer Edition)のカスタムウィジェットで、手元のCSVをアップロードして、地図上に表示するための開発の4回めです。

シリーズ一覧

今回のゴール

レイヤーリストに表示するレイヤー名と、緯度、経度として判断する列名を設定して、配置先環境に合わせた設定ができるようにします。

ウィジェットを追加したとき、構成アイコンをクリックしたとき、以下の画面が開き、設定内容を保存します。

WS000000

設定内容はソースコードから変数として参照するように変更します。

画面作成

まずは、設定を読むように、[Widgetパス]\manifest.jsonを編集。

{
  "name": "CSVLoader",
  "2D": true,
  "3D": true,
  "platform": "HTML",
  "version": "2.0.1",
  "wabVersion": "2.0.1",
  "author": "渡部 潤司",
  "description": "CSVファイルに格納された緯度/経度を利用して、地図上にポイントを表示します。",
  "copyright": "(C) 2016 ハウスソフト",
  "license": "http://www.apache.org/licenses/LICENSE-2.0",
  "properties": {
		"inPanel":true,
		"hasLocale": true,
		"supportMultiInstance":false,
		"hasStyle":true,
		"hasConfig":true,
		"hasUIFile":true,
		"keepConfigAfterMapSwitched":false,
		"hasSettingPage":true,
		"hasSettingUIFile":true,
		"hasSettingLocale":true,
		"hasSettingStyle":false,
		"IsController":false
  }
}

今回の修正点は、

  • “hasSettingPage”:[Widgetパス]\setting\Setting.jsを持っているか否か (設定を処理するJavaScript)
  • “hasSettingUIFile”:[Widgetパス]\setting\Setting.htmlを持っているか否か (設定画面)
  • “hasSettingLocale”:[Widgetパス]\setting\nlsフォルダを持っているか否か (設定画面の多言語対応。必須ではないです)
  • “hasConfig”:[Widgetパス]\setting\config.jsを持っているか否か (設定用変数を保持するファイル)

まず、設定値を持つconfig.js。JSON形式で設定変数を定義しておきます。レイヤ名と、緯度/経度として判断する列名のリスト(半角カンマ区切り)を設定することにしました。

{
    "layerName": "CSV読込(設定)",
    "latColumnName": "Y,緯度,lat,latitude",
    "lonColumnName": "X,経度,lon,longitude"
}

次に設定画面です。シンプルに入力フィールドを並べています。

data-dojo-attach-point=”layerName”の指定は、Dojo Toolkitの書き方でこうすると、ソースコード中からこの変数名に触れる用になります。this.layerName.set(‘value’, 設定値)と書くと、layerNameとつけたタグのvalue属性に設定値を書き込んでくれる。

<div style="width:100%;height:auto;">
    <table>
        <tr>
            <td>${nls.layerName}:</td>
            <td><input type="text" data-dojo-type="dijit/form/TextBox" data-dojo-attach-point="layerName"></input></td>
        </tr>
        <tr>
            <td>${nls.latColumnName}:</td>
            <td><input type="text" data-dojo-type="dijit/form/TextBox" data-dojo-attach-point="latColumnName"></input></td>
        </tr>
        <tr>
            <td>${nls.lonColumnName}:</td>
            <td><input type="text" data-dojo-type="dijit/form/TextBox" data-dojo-attach-point="lonColumnName"></input></td>
        </tr>
    </table>
</div>

最後に、Setting.js。設定画面を開いた時に、保存された設定を画面に表示するためのsetConfig関数と、画面で設定した内容を保存するためのgetConfig関数が必須です。setConfigは自動で呼ばれるかと思ったのですが呼ばれなかったので、startupで明示的に呼ぶようにしています。

define([
    'dojo/_base/declare',
    'dojo/on',
    'dijit/_WidgetsInTemplateMixin',
    'jimu/BaseWidgetSetting',
    ],
function(declare, on, _WidgetsInTemplateMixin, BaseWidgetSetting) {
    return declare([BaseWidgetSetting, _WidgetsInTemplateMixin], {
        startup: function() { 
            this.setConfig(this.config);
        },
        getConfig: function() {
            var config = {
                layerName:this.layerName.value,
                latColumnName:this.latColumnName.value,
                lonColumnName: this.lonColumnName.value
            };      
            return config;
        },
        setConfig: function(config) {
            this.config = config;
            this.layerName.set('value', this.config.layerName);
            this.latColumnName.set('value', this.config.latColumnName);
            this.lonColumnName.set('value', this.config.lonColumnName);
        }
    });
});

多言語対応

ウィジェット自体の多言語対応と同じように、settingフォルダ内にnlsフォルダを作ります。

定義した変数は上のhtmlファイルで${nls.layerName}のように参照されています。

[Widgetパス]\setting\strings.js

define({
  root: {
    "layerName": "Layer Name",
    "latColumnName": "Latitude Column Name in Csv File",
    "lonColumnName": "Longitude Column Name in Csv File"
  },
  "ja": 1
});

[Widgetパス]\setting\js\strings.js

define({
    "layerName": "レイヤ名",
    "latColumnName": "緯度列の名前",
    "lonColumnName": "経度列の名前"
})

追加したポイント全体を表示する

CSV内のポイントデータを追加する際に、x/y座標それぞれの最小値/最大値を取得しておいて、追加終了後に、追加データ数を表示してmapオブジェクトの表示領域を設定。

addObjsToLayer: function(objs) {
    // 緯度、経度をそれぞれ_y,_xプロパティに持っているオブジェクトを受け取り
    // Graphicオブジェクトに変換したうえで自前のGraphicLayerに追加する
    var xmin, xmax, ymin, ymax;
    for (var i = 0; i < objs.length; i++) {
        var x = objs[i]["_x"];
        var y = objs[i]["_y"];
        if (!xmin) {    // 配列に含まれる緯度、経度それぞれの最小値、最大値を取得→最後に表示範囲を設定
            xmin = xmax = x;
            ymin = ymax = y;
        } else {
            if (x < xmin) xmin = x;
            if (x > xmax) xmax = x;
            if (y < ymin) ymin = y;
            if (y > ymax) ymax = y;
        }
        var geometry = new Point(x, y,  new SpatialReference({ wkid: 4326 }));
        var g = new graphic(geometry, this.myLayerSymbol, objs[i]);
        this.myLayer.add(g);
    }
    
    // 追加したアイテム全体を覆う領域を地図の表示領域とする
    var layerExtent = new Extent(xmin, ymin, xmax, ymax, new SpatialReference({ wkid: 4326 }));
    this.map.setExtent(layerExtent);
}

結果

WS000001

追加されたレイヤ名が設定したものに変わりました。

今回作ったウィジェット全体:CSVLoader_v0.4