#29 Thymeleafを利用したSelectボックスの作成

# #29 Thymeleafを利用したSelectボックスの作成
HTMLには``<select>``、``<option>``タグを用いて設定した選択肢の中から値を取得することができます。
しかし、選択肢が少ない場合は良いですが、多くなるといちいち全ての選択肢をHTMLに記述していくのは時間がかかります。
なので、データベースから取り出したデータをThymeleafの繰返し機能を用いて取り出します。

https://developer.mozilla.org/ja/docs/Web/HTML/Element/select

# 前提条件
この記事はSpringの最低限の知識が必要になります。
また、なるべく分かりやすく書くつもりですが、この記事の目的は自分の勉強のアウトプットであるため所々説明は省略します。

# 構築環境
1. 各バージョン
Spring Boot ver 2.7.5
mybatis-spring-boot-starter ver 2.2.2
Model Mapper ver 3.1.0
jquery ver 3.6.1
bootstrap ver 5.2.2
webjars-locator ver 0.46
thymeleaf-layout-dialect ver 3.0.0

2. 依存関係
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/58b53ccd-7cf2-2d82-4214-9f0c08fced2e.png)

# 成果物
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/43bafce5-7c72-8cc6-88cf-9eeb1f1a32c9.png)

# 今回行うこと
1. エンティティクラス(Department.java)の作成
2. データベースへのアクセス処理の作成
　1. レポジトリークラス(MUserMapper.java)にメソッドを定義
　2. 具体的な処理の記述
3. サービス(処理部分)の作成
　1. UserService.java
　2. UserServiceImpl.java 
4. コントローラー(SignupController.java)の作成
5. 画面(signup.html)の作成  

## 1. エンティティクラス(Department.java)の作成
```java:MDepartment.java
package com.example.model;

import lombok.Data;

@Data
public class MDepartment {

	private Integer departmentId;
	private String departmentName;
}
```

## 2. データベースへのアクセス処理の作成
今回使用するテーブル(M_DEPARTMENT)は以下になります。
| DEPARTMENT_ID | DEPARTMENT_NAME |
|      :-:      |       :-:       |
|       1       |      新宿店      |
|       2       |      池袋店      |
|       3       |      渋谷店      |
|       4       |      大宮店      |
|       5       |      横浜店      |

### 1. レポジトリークラス(MUserMapper.java)にメソッドを定義
```java:UserMapper.java
package com.example.repository;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import com.example.model.MDepartment;

@Mapper
public interface UserMapper {
	
	/* 店舗情報を取得 */
	public List<MDepartment> findAllMDepartment();
}
```
### 2. 具体的な処理の記述
```xml:UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<!-- Mapperとxmlのマッピング -->
<mapper namespace="com.example.repository.UserMapper">

<!-- マッピング定義(店舗) -->
<resultMap type="com.example.model.MDepartment" id="department">
	<id column="department_id" property="departmentId" />
	<result column="department_name" property="departmentName" />
</resultMap>
	
	<!-- 店舗の情報全件取得 -->
	<select id="findAllMDepartment" resultType="MDepartment">
		SELECT * FROM M_DEPARTMENT
	</select>

</mapper>
```
## 3. サービス(処理部分)の作成
次に先ほどデータベースから取り出した内容を画面に表示させるための処理を記述していきます。

### 1. UserService.java
今回は戻り値として``Map``を使用します。KeyをString型、ValueをInteger型としておきます。
```java:UserService.java
package com.example.service;

import java.util.List;
import java.util.Map;

public interface UserService {

	/* 店舗のMapを生成する */
	public Map<String, Integer> getDepartmentMap();
}
```
### 2. UserServiceImpl.java 
```java:UserServiceImpl.java
package com.example.service.impl;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.model.MDepartment;
import com.example.repository.UserMapper;
import com.example.service.UserService;

@Service
public class UserServiceImpl implements UserService {
	
	/* レポジトリー(UserMapper.java)のDIを注入 */
	@Autowired
	private UserMapper mapper;
			
	/* 店舗のMapを生成する */
	@Override
	public Map<String, Integer> getDepartmentMap() {

        /* データベースから値を取得 */
		List<MDepartment> mDepartment = mapper.findAllMDepartment();

        /* データベースから取り出した値を格納するためのMapを作成 */
		Map<String, Integer> mDepartmentMap = new LinkedHashMap<>();
		
        /* 拡張for文を用いて取り出したデータを1行ずつ取り出し、IDと名前をMapにセットしていく */
		for(MDepartment row : mDepartment) {
			String departmentName = row.getDepartmentName();
			Integer departementId = row.getDepartmentId();
			mDepartmentMap.put(departmentName, departementId);
		}
		return mDepartmentMap;
	}
}
```

## 4. コントローラー(SignupController.java)の作成
```java:SignupController.java
package com.example.controller;

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.application.service.ApplicationService;
import com.example.service.UserService;


@Controller
@RequestMapping("/user")
public class SignupController {
	
	@Autowired
	private UserService userService;
	
	/* ユーザー登録画面を表示 */
	@GetMapping("/signup")
	public String getSignup(Model model) {
		
		// 店舗を取得
		Map<String, Integer> mDepartmentMap = userService.getDepartmentMap();
		model.addAttribute("mDepartmentMap", mDepartmentMap);
		
		// ユーザー登録画面に遷移
		return "user/signup";
	}
}
```

## 5. 画面(signup.html)の作成  
```html:signup.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="wiewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- 省略 -->
</head>
<body class="bg-light">
	<!-- 店舗名 -->
	<div class="form-group">
		<label for="departmentId">店舗名</label>
		<select class="dropdown form-control">
			<option th:value="0"></option>
			<option th:each="item : ${mDepartmentMap}" th:value="${item.value}" th:text="${item.key}"></option>
		</select>
	</div>		
</body>
</html>
```
<br>

先ほどコントローラーでModelに格納した``mDepartmentMap``を``th:each``文を用いて繰返します。
その際、渡す値は``th:value="${item.value}"``、画面に表示する値は``th:text="${item.key}"``として設定します。
また、``<option th:value="0"></option>``を個別に設定して何も選択しなかった場合、自動的に``value="0"``を渡すようにしています。
```html
		<select class="dropdown form-control">
			<option th:value="0"></option>
			<option th:each="item : ${mDepartmentMap}" th:value="${item.value}" th:text="${item.key}"></option>
		</select>
```

# 最後に
以上でThymeleafを利用したSelectボックスの作成が完了しました。
今回CSSの記述は省略しています。