BODIK APIを使ったJavascriptプログラムを書いてみます。
課題3:BODIK APIの検索結果を表で表示する
問題:BODIK APIを使って、AEDを検索し、結果を表で表示する。
基本情報
- Javascriptでスプレッドシートを表示する場合、「AG-Grid」というライブラリを使うと便利です。
- JavascriptでAG-Gridを使うためには、ライブラリをインポートする必要があります。
- AG-Gridの詳細は公式HPをご参照ください。
AG-Grid: https://www.ag-grid.com/
Javascriptで記述
最初に、Javascriptで「BODIK API」を呼び出してみましょう。今回はfeatureのproperties部分だけを抜き出して、配列に格納します。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>BODIK API</title> <script type="text/javascript"> let api_server = 'https://wapi.bodik.jp'; let api = 'aed'; let lat = 33.59334325082392; let lon = 130.35598920962553; let api_url = `${api_server}/${api}`; fetch(api_url) .then(response => response.json()) .then(data => { let array = []; for (let feature of data['resultsets']['features']) { let properties = feature['properties']; array.push(properties); } let output = document.getElementById('output'); output.innerHTML = JSON.stringify(array, null, 2); }); </script> </head> <body> <h2>BODIK API program #3</h2> <pre id="output"></pre> </body> </html>
このpropertiesの配列をスプレッドシートに表示すればいいですね。
Javascriptでスプレッドシートを表示
Javascriptでスプレッドシートを表示する方法として、AG-Gridが便利です。
AG-Gridは無料で使えるOSSですが、正しく使うためにはライセンス表記が必要になります。(今回は省略します。)
AG-Gridを使うためには、AG-GridのライブラリとCSSを参照します。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>BODIK API</title> <script src='https://cdnjs.cloudflare.com/ajax/libs/ag-grid/30.2.0/ag-grid-community.min.js'></script> <link href="https://unpkg.com/gridjs/dist/theme/mermaid.min.css" rel="stylesheet"> </head> <body> <h2>BODIK API program #3</h2> <div id="gripdarea" style="width:800px;height:600px"> <div id="grid" class="ag-theme-balham" style="width:100%;height:100%"></div> </div> </body> </html>
AG-Gridのデータ構造
PCの世界でスプレッドシートというと「CSV」を表示するイメージですが、AG-GridはJSONを表示するツールです。
次のようなCSVのデータを表示するサンプルとします。
id,name,age 0001,佐藤,25 0002,鈴木,30 0003,田中,35
データ
スプレッドシートに表示する1行分のデータをJavascriptの辞書データで定義します。その辞書データの配列をスプレッドシートのデータとします。
// データ let row_data = [ { 'id': '0001', 'name': '佐藤', 'age': 25 }, { 'id': '0002', 'name': '鈴木', 'age': 30 }, { 'id': '0003', 'name': '田中', 'age': 35 } ]
ヘッダー
スプレッドシートの列項目部分のデータをヘッダーとして与えます。ヘッダーは次のような構造です。
// ヘッダー let header_data = [ { 'field': 'id', 'headerName': 'ID' }, { 'field': 'name', 'headerName': '名前' }, { 'field': 'age', 'headerName': '年齢' } ]
BODIK APIと組み合わせる
BODIK APIの検索結果をAG-Gridに表示する方法を考えてみましょう。
このページの最初の例で試したように、BODIK APIが返す検索結果から、featureのproperties部分は辞書になっていますから、これを取り出して配列に格納すれば、その配列はAG-Gridに与える「データ」となります。
あとはヘッダーを作れば良いですね。次のように先頭データ(辞書)から項目名を取り出しましょう。
let header_data = []; // AG-Gridのヘッダー情報 let feature0 = features[0]; // 最初のデータを取り出す let properties0 = feature0['properties']; // propertiesを取り出す let headers = Object.keys(properties); // 辞書から項目名の配列を作る for (let fld of headers) { // 項目名の配列から順番に取り出す let col = { 'headerName': fld, 'fld': fld } header_data.push(col); }
次のコードでも同じ処理ができます。
let header_data = []; // AG-Gridのヘッダー情報 let feature0 = features[0]; // 最初のデータを取り出す let properties0 = feature0['properties']; // propertiesを取り出す for (let fld in properties0) { // 辞書の項目を順番に取り出す let col = { 'headerName': fld, 'fld': fld } header_data.push(col); }
では、BODIK APIの検索結果をAG-Gridに表示してみましょう。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>BODIK API</title> <script src='https://cdnjs.cloudflare.com/ajax/libs/ag-grid/30.2.0/ag-grid-community.min.js'></script> <link href="https://unpkg.com/gridjs/dist/theme/mermaid.min.css" rel="stylesheet"> <script type="text/javascript"> // BODIK APIを呼び出す let api_server = 'https://wapi.bodik.jp'; let api = 'aed'; let api_url = `${api_server}/${api}?maxResults=100`; fetch(api_url) .then(response => response.json()) .then(data => { let features = data['resultsets']['features'] show_data(features); // AG-Gridに表示する部分を関数として切り出す。 }); function show_data(features) { try { // 最初のデータから項目名を抜き出す let item0 = features[0]['properties']; let headers = Object.keys(item0); // 表の列名を作成する let header_data = []; for (let fld of headers) { let col = { 'headerName': fld, 'field': fld }; header_data.push(col); } // 表のデータ配列を作成する let row_data = []; for (let feature of features) { row_data.push(feature['properties']) } // 表を表示する let grid_options = { 'columnDefs': header_data, 'rowData': row_data } let grid = document.getElementById('grid'); new agGrid.Grid(grid, grid_options); } catch(error) { alert('show_data:' + error); } } </script> </head> <body> <h2>BODIK API program #3</h2> <div id="gripdarea" style="width:800px;height:600px"> <div id="grid" class="ag-theme-balham" style="width:100%;height:100%"></div> </div> </body> </html>
行の選択処理
行をクリックしたときに、その選択された行のデータを表示してみます。
行選択のイベントハンドラを追加します。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>BODIK API</title> <script src='https://cdnjs.cloudflare.com/ajax/libs/ag-grid/30.2.0/ag-grid-community.min.js'></script> <link href="https://unpkg.com/gridjs/dist/theme/mermaid.min.css" rel="stylesheet"> <script type="text/javascript"> let grid_options = null; // 関数間で共有するので、グローバル変数とする // BODIK APIを呼び出す let api_server = 'https://wapi.bodik.jp'; let api = 'aed'; let api_url = `${api_server}/${api}?maxResults=100`; fetch(api_url) .then(response => response.json()) .then(data => { let features = data['resultsets']['features'] show_data(features); }); function show_data(features) { try { // 最初のデータから項目名を抜き出す let item0 = features[0]['properties']; let headers = Object.keys(item0); // 表の列名を作成する let header_data = []; for (let fld of headers) { let col = { 'headerName': fld, 'field': fld }; header_data.push(col); } // 表のデータ配列を作成する let row_data = []; for (let feature of features) { row_data.push(feature['properties']) } // 表を表示する grid_options = { 'columnDefs': header_data, 'rowData': row_data, 'rowSelection': 'single', // 行選択を有効にする 'onSelectionChanged': onSelectionChanged // 行選択のイベントハンドラを指定 } let grid = document.getElementById('grid'); new agGrid.Grid(grid, grid_options); } catch(error) { alert('show_data:' + error); } } // 行選択のイベントハンドラ function onSelectionChanged() { try { const selectedRow = grid_options.api.getSelectedRows(); let selected = selectedRow[0]; alert(JSON.stringify(selected)); } catch(error) { alert('onSelectionChanged:' + error); } } </script> </head> <body> <h2>BODIK API program #3</h2> <div id="gripdarea" style="width:800px;height:600px"> <div id="grid" class="ag-theme-balham" style="width:100%;height:100%"></div> </div> </body> </html>
お疲れ様でした。