Power PagesにJavaScriptで郵便番号検索を実装してみた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140547/9b45aab8-e0a7-2bbc-00b3-fbf546e170ca.png)
前回に引き続き、Preview版のPower Pagesをハックしていきます。
今回は、標準の機能では提供されていない、郵便番号検索を実装します。

具体的には、Power PagesがレンダリングしているHTMLのDOMを調べて、そこにJavaScriptで直接ボタンオブジェクトを書き込み、そのボタンが押されたら郵便番号検索APIからデータ取得した住所データを表示するということをやってみたいと思います。

えぇ、、ちょっと自分でも「何言ってるのか、よくわからない」んですよ😁

## まずはフィードバックテーブルに列を追加
Power Pagesのサンプルにある「お問い合わせ」ページに使われているテーブル「フィードバック」に「郵便番号」と「住所」を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140547/71496622-9bd5-473a-7801-8bc818ce0bd4.png)

ページのフォームにも追加した列を「フィールドを編集する」ボタンから表示させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140547/44194930-c968-8a84-a1bf-1aee4fa1f8ee.png)

「フィールドの追加」から「郵便番号」「住所」を選び「保存」→「フォームの公開」をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140547/6d945283-19ce-58f8-4f29-9f91e2bd4744.png)

そうすると、こんな感じで郵便番号と住所がフォームに表示される筈です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140547/0cdeb6db-5c9a-61a8-43e7-106985f8d7e8.png)

### 編集画面からソースを確認してみる
Power Pagesの編集画面で「お問い合わせページ」の「ソースコード編集ボタン」を押して、フォームが表示されているソース部分を確認すると、この部分は実際にページを公開して表示する際に、プログラムで読み込まれるように記載されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140547/e36639f1-fe3c-0512-bc68-704591d06f69.png)

## 郵便番号検索を実装してみる
Power Pagesは、フォームの部分については、ノーコーディングなので先程のように選んで追加するだけです。
しかも編集画面でもフォーム部分はHTMLソースを編集することができないので、郵便番号検索ボタンは通常は付けられませんが、公開して表示されたページのDOMを調べてJavaScriptを使って指定の場所に書き出せるかテストしてみます。

:::note info
DOMについて詳しく知りたい方は、下記ページ参照してください。
[「DOMとは」](https://www.javadrive.jp/javascript/dom/index1.html#:~:text=DOM%20%E3%81%A8%E3%81%AF%20Document%20Object,%E3%81%8C%E8%A1%8C%E3%82%8F%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82)
:::

### 郵便番号検索API
問い合わせフォームでは、郵便番号検索機能がついていると思うのですが、データから自前で作成するとメンテナンスも大変なので、外部サービスとして「zipcloud」のAPIサービスを利用させていただきます。

[zipcloud](http://zipcloud.ibsnet.co.jp/)

先程の「郵便番号」に郵便番号を入れて検索したら「住所」に住所が入ってくる想定です。

### ブラウザで当該の場所を調べる
Power Pagesで対象となる「お問い合わせページ」をブラウザで表示して「デベロッパーモード」（Cntrl+Shift+I）を呼び出し、フォーム部分のHTMLを調べます。

画面左上の「ソース指定ボタン（正式名称わかりませんｗ）」を押して、郵便番号入力部分をクリックするとHTMLの当該の部分のソースを教えてくれます。

Power Pagesの郵便番号部分を指定してみると、入力ボックスをTableタグで囲っていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140547/dbe30e40-d47e-95da-6873-e10c7da1f7de.png)

### JavaScriptで指定箇所にボタンを書き出してみる
Power Pagesの編集画面に戻り、お問い合わせページのソース編集画面に、以下のJavaScriptのコードを一番下に貼り付けます。

```
<script>
  let zipcode = document.querySelector("#EntityFormControl_7afb648fd6dbec11bb3c000d3a40b515_EntityFormView > div.tab.clearfix > div > div > fieldset > table > tbody > tr:nth-child(6) > td.clearfix.cell.text.form-control-cell");
  zipcode.insertAdjacentHTML('beforeend', '<button type="button" id="searchBtn">郵便番号検索</button>');
</script>
```
1行目：zipecodeという変数にdocument.querySelectorで指定したパスを代入します。
このカッコの中身はtableのtdタグまでのパスが記載されています。
本当はid名があればそのid名を記載すれば取得できますが、Power Pagesのtdタグにはid名が指定されていないので、このように指定しています。

2行目：insertAdjacentHTMLは、指定した場所に要素を追加するのですが、第一引数の「beforeend」で「指定要素の最後に」といった意味になります。第二引数は書き出したいタグを書きます。

:::note info
指定箇所までのパスの取得方法は、自分で調べると大変なのでブラウザのデベロッパーツールで要素を右クリックして「JSパスをコピー」で取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140547/68283418-31a0-a695-07b7-56f0ec64721c.png)
:::

### 実際のブラウザで確認してみる
編集画面右上の「同期」ボタンと「プレビュー」ボタンを押すと、、、、
こんな感じでボタンが書き出されているのが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140547/ea3da105-71cd-0cc8-5882-c0fc5ee5d927.png)

## 郵便番号検索の実装
これまでの要素へのアクセスをまとめてJavaScriptで実装します。

以下参考にしています。
[Adobe-Marketing-Cloud/fetch-jsonp](https://github.com/Adobe-Marketing-Cloud/fetch-jsonp)
[郵便番号検索APIで住所検索を実装する](https://into-the-program.com/javascript-get-address-zipcode-search-api/)

APIへのアクセスには「fetch-jsonp」を利用しています。こちらをCDNから読み込みます。
```
<script src="https://cdn.jsdelivr.net/npm/fetch-jsonp@1.1.3/build/fetch-jsonp.min.js"></script>

```

1行目から4行目：表示させたいボタンやエラーの際に文字を表示する場所を書き出しています。
5行目以降：出力したボタンの位置を取得して、addEventListenerでボタンクリックを取得します。
クリックされたら、zipcloudへ送るURLを、入力された郵便番号を文字列として生成し、fetch-jsonpで送信してあげます。
data.resultsとして、配列で戻ってきますので、取り出した都道府県や住所の文字列を連結して、住所のinputに返してあげます。
```
<script>
  let zipcode = document.querySelector("#EntityFormControl_7afb648fd6dbec11bb3c000d3a40b515_EntityFormView > div.tab.clearfix > div > div > fieldset > table > tbody > tr:nth-child(6) > td.clearfix.cell.text.form-control-cell");
  zipcode.insertAdjacentHTML('beforeend', '<button type="button" id="searchBtn">郵便番号検索</button>');
  zipcode.insertAdjacentHTML('beforeend', '<span id="error"></span>');


  let search = document.querySelector("#searchBtn");
  search.addEventListener('click', () => {
    let api = 'https://zipcloud.ibsnet.co.jp/api/search?zipcode=';
    let error = document.getElementById('error');
    let input = document.getElementById('cr131_zipcode');
    let address = document.getElementById('cr131_address');
    let param = input.value.replace("-", ""); 
    let url = api + param;
    fetchJsonp(url, {
        timeout: 10000, 
      })
      .then((response) => {
        error.textContent = ''; 
        return response.json();
      })
      .then((data) => {
        if (data.status === 400) { 
          error.textContent = data.message;
        } else if (data.results === null) {
          error.textContent = '郵便番号から住所が見つかりませんでした。';
        } else {
          address.value = data.results[0].address1 + data.results[0].address2 + data.results[0].address3;
        }
      })
      .catch((ex) => { //例外処理
        console.log(ex);
      });
  }, false);
</script>
```

## テストしてみる
郵便番号を入力して、「郵便番号検索」ボタンを押すと、、、
住所部分に取得した住所の文字列が並んでいるのがわかります。
登録ボタンを押すとDataverseにデータが保存されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140547/b05ee8d7-b56c-eb1a-70e9-fba48281ea2f.png)

Power Pagesのトップページにリストを作成して、データベースの一覧を表示してみると、郵便番号と住所が登録されていることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140547/e1fe2310-8f65-dabf-ba3e-2fb4ee640a08.png)

JavaScriptからコントロール出来ると、コネクタを使うようにPower Pagesで色々なデータを取得してくることが可能になり、拡張性が増えました。

次回はGoogle Mapで現在地を取得して、地図にマッピングとかやってみたいと思います。