Spring Boot + npm + Geb で入力フォームを作ってテストする ( その25 )( 入力画面2を作成する4 )
概要
記事一覧はこちらです。
Spring Boot + npm + Geb で入力フォームを作ってテストする ( その24 )( 入力画面2を作成する3 ) の続きです。
参照したサイト・書籍
Autocomplete | jQuery UI
https://jqueryui.com/autocomplete/[jQuery UI] AutocompleteのソースをAjaxで取得する
http://www.84kure.com/blog/2015/07/27/jquery-ui-autocompleteのソースをajaxで取得する/1分でわかるjQuery $.ajaxによるJSON・JSONP読み込み方法
https://iwb.jp/jquery-ajax-jsonp/Display jquery ui auto-complete list on focus event
https://stackoverflow.com/questions/4132058/display-jquery-ui-auto-complete-list-on-focus-eventAJAX通信をするときはタイムアウト処理を必ず入れてほしい(切実)
https://qiita.com/tonkotsuboy_com/items/d1b3cf45ae5135441f9bHow to include jQuery UI into my project using Webpack?
https://stackoverflow.com/questions/38796673/how-to-include-jquery-ui-into-my-project-using-webpack
目次
手順
npm で jquery-ui をインストールする
郵便番号を入力したら jQuery-UI の autocomplete で「住所」の入力項目の下にドロップダウンリストを表示して選択できるようにします。
admin-lte パッケージ内の plugins/jQueryUI の下には js ファイルしかないのですが、autocomplete の表示には css ファイルも必要なので npm で jquery-ui パッケージをインストールします。
npm install --save jquery-ui
コマンドを実行して jQueryUI をインストールします。
package.json に jquery-ui の css をコピーする npm-scirpts を追加します。
"scripts": { .......... "copy:all": "run-p copy:bootstrap copy:admin-lte copy:font-awesome copy:ionicons copy:jquery-ui-css", .......... "copy:ionicons": "cpx node_modules/ionicons/dist/{css,fonts}/**/* src/main/resources/static/vendor/ionicons", "copy:jquery-ui-css": "cpx node_modules/jquery-ui/themes/base/**/* src/main/resources/static/vendor/jquery-ui/css", .......... },
"copy:jquery-ui-css": "cpx node_modules/jquery-ui/themes/base/**/* src/main/resources/static/vendor/jquery-ui/css"
を追加します。copy:all
の最後にcopy:jquery-ui-css
を追加します。
npm run copy:jquery-ui-css
コマンドを実行して css ファイルをコピーします。
入力された郵便番号の住所一覧を jQuery-UI の autocomplete で表示・選択する処理を実装する
src/main/assets/js/inquiry/input02.js を以下のように変更します。
"use strict"; var Form = require("lib/class/Form.js"); var converter = require("lib/util/converter.js"); var validator = require("lib/util/validator.js"); require("jquery-ui/ui/widgets/autocomplete.js"); .......... var addressList = []; var findAddressListByZipCode = function (event) { // 入力チェックエラーが発生している場合には処理を中断する if (event.isPropagationStopped()) { return; } // 郵便番号の入力項目全てにフォーカスがセットされていなければ処理を中断する if (!form.isAllFocused(form, ["#zipcode1", "#zipcode2"])) { return; } // 郵便番号検索APIで住所を検索する addressList = []; $.ajax({ type: "get", url: "http://zipcloud.ibsnet.co.jp/api/search", data: {zipcode: $("#zipcode1").val() + $("#zipcode2").val()}, cache: false, dataType: "jsonp", jsonpCallback: "callback", timeout: 5000 }).then( function (json) { if (json.status === 200) { if (json.results === null) { form.setError("#form-group-address", "郵便番号に該当する住所はありませんでした"); return; } json.results.forEach(function (result) { addressList.push(result.address1 + result.address2 + result.address3); }); // 「住所」の入力項目の下に autocomplete のドロップダウンリストを表示する if ($("#address").is(":focus")) { $("#address").autocomplete("search"); } } else { form.setError("#form-group-address", json.message); } }, function () { form.setError("#form-group-address", "郵便番号APIの呼び出しに失敗しました"); } ); }; .......... $(document).ready(function () { // 入力チェック用の validator 関数をセットする .......... // 入力された郵便番号から住所を取得する処理をセットする $("#address").on("focus", findAddressListByZipCode); $("#address").autocomplete({ // source には addressList 変数を直接指定するのではなく、 // 関数を渡して findAddressListByZipCode 関数で変更された addressList // のデータが表示されるようにする source: function (request, response) { // 「住所」に何も入力されていない時だけドロップダウンリストを表示する if ($("#address").val() === "") { response(addressList); } else { response([]); } }, // minLength: 0 を指定しないと findAddressListByZipCode 関数内で // $("#address").autocomplete("search"); を呼び出した時にドロップダウンリスト // が表示されない minLength: 0 }); .......... });
require("jquery-ui/ui/widgets/autocomplete.js");
を追加します。var addressList = [];
を追加します。findAddressListByZipCode
関数を追加します。$(document).ready(function () { ... }
の以下の点を変更します。["#zipcode1", "#zipcode2"].forEach(function (id) { $(id).on("blur", findAddressListByZipCode); });
を追加します。$("#address").autocomplete({ ... });
を追加します。
src/main/resources/templates/web/inquiry/input02.html の以下の点を変更します。
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head th:replace="~{web/common/fragments :: common_header(~{::title}, ~{::link}, ~{::style})}"> <title>入力フォーム - 入力画面2</title> <link rel="stylesheet" href="/vendor/jquery-ui/css/all.css"> </head> ..........
<link rel="stylesheet" href="/vendor/jquery-ui/css/all.css">
を追加します。
ここまでの実装で npm run springboot
コマンドを実行すると、Module not found: Error: Can't resolve 'jquery' in ...
というエラーメッセージが大量に出力されます。
webpack.config.js で jquery
の alias を定義すればこのエラーは出なくなります。以下のように変更します。
resolve: { modules: [ "node_modules", "src/main/assets/js" ], alias: { jquery: "admin-lte/plugins/jQuery/jquery-2.2.3.min.js" } },
alias: { jquery: "admin-lte/plugins/jQuery/jquery-2.2.3.min.js" }
を追加します。
再び npm run springboot
コマンドを実行すると今度はエラーが出ません。
動作確認
動作確認します。npm run springboot
コマンドは実行済なので、Tomcat を起動した後、ブラウザで http://localhost:9080/inquiry/input/01/ にアクセスします。
データを入力してから、「次へ」ボタンをクリックして入力画面2へ遷移します。
「郵便番号」に 079-0177
を入力して「住所」にフォーカスを移動すると、フォーカスが移動した直後はドロップダウンリストは表示されませんが、郵便番号検索APIの検索が終了するとドロップダウンリストが表示されます。
上下矢印キーで選択すると、選択された項目が「住所」の入力項目にセットされます。
選択してから追加で "1丁目" と入力しても特に動作には問題はありません。
存在しない郵便番号を入力すると「住所」の入力項目の下に "郵便番号に該当する住所はありませんでした" のメッセージが表示されます。
次回は。。。
サーバ側のテストを書きます。
履歴
2017/10/10
初版発行。