目次
作成するもの
SpringBootで、追加ボタンをクリックすると、入力フォームが増えるような、動的フォームを作成しますjQueryのajaxとThymleafのfragmentを使用して、画面遷移をせず画面の一部のみ更新するようにしています
完成したもの
プロジェクトの作成
使用するもの
プロジェクトを作成する前に今回私が使用するライブラリやIDEとバージョンを載せておきます- Eclipse 2022-06
- jQuery 3.6.0
Spring Initializerを使用して、プロジェクトを作成していきます
SpringInitializrは条件に合わせてSpringBootプロジェクトの雛形を生成するWebサービスです
【URL】 https://start.spring.io/
必要最低限のライブラリとして、SpringWebとThymeleafをDependenciesに追加しています
その他デフォルトのままで
GENERATEボタンをクリックすると、zipファイルがダウンロードされます
解凍してEclipseにインポートします
フォームの作成
まずは、通常の入力フォームと、入力したデータをコントローラで受け取り、結果を画面表示できるようにします特に、変なことはしていないので、コードだけ載せておきます
動作確認
fragmentの導入、入力フォームの追加(まだ動的フォームにはしない)
fragmentとは、th:fragment 属性を指定した要素を、別の箇所に th:insert や th:replaceで埋め込むことができる機能ですfragmentを利用し、動的フォーム部分のhtmlを部品化していきます
修正したコードのみ載せます
現状のフォルダ構成
demo
> src/main/java
> com.example.demo
> controller
> PersonForm.java
> ProgrammingLanguage.java ←新規作成
> WelcomeController.java
> DemoApplication.java
> src/main/resources
> static
> templates
> fragments.html ←新規作成
> index.html
> result.html
> application.properties
// 以下省略
PersonForm.java
まずは、フォームクラスを修正して、フィールドを追加します動的フォーム(入力数が可変)のため、Listにしておきます
public class PersonForm {
private String name;
private <ListProgrammingLanguage> programmingLanguageList;
public PersonForm() {
programmingLanguageList = new ArrayList();
programmingLanguageList.add(new ProgrammingLanguage());
}
}
ProgrammingLanguage.java
続いて、先ほど追加したListの要素となるクラスですpublic class ProgrammingLanguage {
private String name;
private Integer yearsOfExperience;
// GetterSetter省略
}
fragments.html
動的フォームにする部分はfragmentを使用して別のhtmlファイルに記述します<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<!-- th:framnetでfragment名を指定します -->
<div id="programmingLanguage" th:fragment="programmingLanguage" th:object="${personForm}">
<div th:each="programmingLanguage, stat : *{programmingLanguageList}">
プログラミング言語
<!-- __${}__ で囲ったところがthymelafによって先に評価されます-->
<input type="text" th:field="*{programmingLanguageList[__${stat.index}__].name}">
実務経験
<input type="number" th:field="*{programmingLanguageList[__${stat.index}__].yearsOfExperience}">
年
</div>
</div>
</html>
index.html
次に、index.htmlの修正です<th:block>…</th:block>の部分がfragments.htmlの<div th:fragment=”programmingLanguage”>…</div>に置き換わります
<body>
<form id="form" th:action="@{/result}" method="post" th:object="${personForm}">
<div>
名前:<input type="text" th:field="*{name}">
<!-- th:replaceにはファイル名::fragment名を指定 -->
<th:block th:replace="fragments::programmingLanguage"></th:block>
</div>
<input type="submit" value="送信">
</form>
</body>
result.html
結果表示画面も微修正します<body>
<div th:object="${personForm}">
名前:<span th:text="*{name}"></span> <br>
<th:block th:each="programmingLanguage, stat : *{programmingLanguageList}">
プログラミング言語:<span th:text="*{programmingLanguageList[__${stat.index}__].name}"></span>
実務経験:<span th:text="*{programmingLanguageList[__${stat.index}__].yearsOfExperience}"></span>年
<br>
</th:block>
</div>
</body>
動作確認
ajaxと動的フォームの実装
追加ボタンの追加、追加ボタンクリックで入力フォームが増えるようにしますfragment.html
まずは、fragment.htmlを修正していきます変更点としては、追加ボタンを追記しています
inputのtypeはsubmitではなくbuttonとし、onclickにこれから実装するfunction名を指定します
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div id="programmingLanguage" th:fragment="programmingLanguage" th:object="${personForm}">
<div th:each="programmingLanguage, stat : *{programmingLanguageList}">
プログラミング言語
<input type="text" th:field="*{programmingLanguageList[__${stat.index}__].name}">
実務経験
<input type="number" th:field="*{programmingLanguageList[__${stat.index}__].yearsOfExperience}">年
</div>
<input type="button" onclick="addForm()" value="追加">
</div>
</html>
index.html
追加ボタンが押された時の処理を記載していきます<body>
<form id="form" th:action="@{/result}" method="post" th:object="${personForm}">
<!-- 変更点ないため省略-->
</form>
<!-- jQueryはCDNで利用します CDNのコードは以下サイトから取得できます
Slim版ではAjaxが利用できないので、通常版を使用してください
jQuery CDN – Latest Stable Versions
-->
<script src="https://code.jquery.com/jquery-3.6.0.js"
integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
crossorigin="anonymous">
</script>
<script>
function addForm(){
$.ajax({
url:"/addForm", // リクエストの送信先
type:"POST", // 使用するHTTPメソッドのタイプ
data:$("#form").serialize(), // 送信するデータ (id="form"内のデータを取得している)
dataType:"html", // 応答のデータの種類
}).done(function(data){ // 通信成功時の処理
$("#programmingLanguage").html(data); // id="programmingLanguage"内のhtmlを応答データに置き換えている
});
}
</script>
</body>
WelcomeController.java
追加ボタンをクリックすることで、/addFormにリクエストが送信されるので、コントローラーの処理を追加する@Controller
public class WelcomeController {
//省略
// 以下メソッドを追加
@PostMapping("/addForm")
public String addForm(@ModelAttribute("personForm")PersonForm personForm) {
// programmingLanguageListの要素を1つ増やすメソッドを呼んでいる(この後実装する)
personForm.addForm();
// returnにはfragmentを指定する
return "fragments::programmingLanguage";
}
}
PersonForm.java
public class PersonForm {
// 省略
// 以下のメソッドを追加する
public void addForm() {
programmingLanguageList.add(new ProgrammingLanguage());
}
}