Thymeleaf Springbootメモ

# 概要
thymeleafでよく使った構文をまとめます。
後でデバッグして確認したいのでgithubにまとめます。


# 開発環境
OS：Windows10
IDE:IntelliJ comunnity
Javaバージョン：11(pom.xmlでバージョン変えればok、17は確認済み)
Spring bootバージョン：2.7.0
thymeleafバージョン：3.0.15.RELEASE


# フォルダ構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/71fd8cc9-c899-841a-5d34-a1e366464a3b.png)

赤丸で囲まれた部分を見ます

# 実行方法
1.githubからプロジェクトをクローンします。branchは「thymeleaf」を選択します。
https://github.com/RYA234/spring_boot_memo

2.src/main/java/com/example/spring_boot_memo/**SpringBootMemoApplication**を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/f8b27e36-e006-8a51-e173-5086c2ea01c3.png)

3.以下URLを開きます
http://localhost:5000/
開くと以下画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/295b52c8-240b-5fec-1243-db3a573071ac.png)



# 内容
## 1 コントローラーからhtml側に変数を渡す。

**Controller側の処理**
int型の変数Countを宣言します。値は1234とします。
model.addAttribute()でview側にCountの値を渡します。
OKとNGとも同じ処理をしています。

**view側の処理**
Controllerで渡された変数を表示します。
OKとNGで変数部分が違うのでエラーになります。


### OKな場合
Controller
``` Controller.java
    @RequestMapping(value = "thymeleaf/1_menu", params = "OK", method = RequestMethod.POST)
    public String thymeleaf_1_menuOkController(Model model)
    {
        int Count = 1234;
        model.addAttribute("CountName",Count);
        return "thymeleaf/1_menu_ok";
    }

```

html

``` 1_menu_ok.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>1.コントローラーから関数に渡す_OK</title>
</head>
<body>

    コントロールからの値の取得に成功しました。
    CountNameの値は<div th:text="${CountName}"></div>

</body>
</html>

```
表示結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/44a33492-2ec4-e894-55fe-fb691caf82d5.png)

### NGな場合

Controller
``` Controller.java
    @RequestMapping(value = "thymeleaf/1_menu", params = "NG", method = RequestMethod.POST)
    public String thymeleaf_1_menuNgController(Model model)
    {
        int Count = 1234;
        model.addAttribute("CountName",Count);
        return "thymeleaf/1_menu_ng";
    }
```

html

``` 1_menu_ng.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>1.コントローラーから関数に渡す_NG</title>
</head>
<body>
このページは表示されず Whitelabel Error Pageが表示されます。
CountNameの値は<div th:text="{CountName}"></div>
<!--th:text="{CountName}"だとNGになる　-->
</body>
</html>

```
表示結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/86c0ad50-0728-4a1c-ef56-9df0bb7bf791.png)


エラー箇所の発見方法
ブラウザ上で「line」を検索するとエラー箇所を特定できます。

今回の事例に当てはめますと「Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: "{CountName}" (template: "thymeleaf/1_menu_ng" - **line 10, col 18**)」

1_menu_ng.htmlの10行目にエラーがあると確認できます。


## 2 コントローラーからhtml側にクラスを渡す場合
変数を渡すときとは表記の仕方が若干かわります。
変数とクラスの渡し方を把握しとかないとごっちゃになり汚いソースコードになります。（経験談）

### OKな場合
Controller
``` Controller.java
    @RequestMapping(value = "thymeleaf/2_menu", params = "OK", method = RequestMethod.POST)
    public String thymeleaf_2_menuOkController(Model model)
    {
        ModelForm modelForm = new ModelForm();
        modelForm.setCount(123);
        modelForm.setName("NAMAE");
        model.addAttribute(modelForm);

        return "thymeleaf/2_menu_ok";
    }
```
html
``` 2_menu_ok.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>2.コントローラーからhtml側にクラスを渡す_OK</title>
</head>
<body>
コントロールからの値の取得に成功しました
<div th:object ="${modelForm}">
    countは<div th:text="*{count}" th:name="*{count}"></div>
    です。
    </bn></br>
    nameは<div  th:text="*{name}" th:name="*{name}"></div>
    です。
</div>


</body>
</html>
```

表示結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/57875272-247d-91af-b4d5-c52c15eb164a.png)

### NGな場合
Controller
``` Controller.java
    @RequestMapping(value = "thymeleaf/2_menu", params = "NG", method = RequestMethod.POST)
    public String thymeleaf_2_menuNgController(Model model)
    {
        ModelForm modelForm = new ModelForm();
        modelForm.setCount(123);
        modelForm.setName("NAMAE");

        model.addAttribute(modelForm);

        return "thymeleaf/2_menu_ng";
    }

```
html
``` 2_menu_ng.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>2.コントローラーからhtml側にクラスを渡す_NG</title>
</head>
<body>
このページは表示されず Whitelabel Error Pageが表示されます。
<div th:object ="${ModelForm}">
    countは<div th:text="${count}" th:name="${count}"></div>
    です。
    </bn></br>
    nameは<div th:text="${name}" th:name="${name}"></div>
    です。
</div>


</body>
</html>
```


表示結果
Chrome検証機能から値が入っていないことを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/abfbc38d-ef3c-b121-abb6-0a76b6f54a58.png)


エラー箇所の発見方法
Chromeの検証機能で確認します。

## 3 html側からコントローラーに変数を渡す場合
### OKな場合
Controller
``` Controller.java
    @RequestMapping(value = "thymeleaf/3_menu", params = "OK", method = RequestMethod.POST)
    public String thymeleaf_3_menuOkController(Model model,ModelForm modelForm)
    {
        System.out.print("3_okのmodelFormについて");
        System.out.print(modelForm);
        return "thymeleaf/3_menu_ok";
    }

```
html
``` 3_menu_ok.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>3.コントローラーからhtml側にクラスを渡す_OK</title>
</head>
<body>
コントロールからの値の取得に成功しました
<div th:object ="${modelForm}">
    countは<div th:text="*{count}" th:name="*{count}"></div>
    nameは<div th:text="*{name}" th:name="*{name}"></div>
    です。
    </bn></br>
    です。
</div>


</body>
</html>
```

表示結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/51e6879e-a995-e8b8-3adc-3e2825ad6f60.png)


### NGな場合
Controller
``` Controller.java
    @RequestMapping(value = "thymeleaf/3_menu", params = "NG", method = RequestMethod.POST)
    public String thymeleaf_3_menuNgController(Model model,ModelForm modelForm)
    {
        System.out.print("3_ngのmodelFormについて");
        System.out.print(modelForm);
        return "thymeleaf/3_menu_ng";
    }
```
html
``` 3_menu_ng.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>3.コントローラーからhtml側にクラスを渡す_NG</title>
</head>
<body>
コントロールからの値の取得に失敗しました
<div th:object ="${modelForm}">
    countは<div th:text="${count}" th:name="${count}"></div>
    nameは<div th:text="${name}" th:name="${name}"></div>
    です。
 </br>
    です。
</div>


</body>
</html>

```


表示結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/2fe63961-5588-3109-97ee-5ce1a90f9dbd.png)


エラー箇所の発見方法
Chromeの検証機能で確認します。

## 4 繰り返しをする場合
### OKな場合
Controller
``` Controller.java
    @RequestMapping(value = "thymeleaf/4_menu", params = "OK", method = RequestMethod.POST)
    public String thymeleaf_4_menuOkController(Model model)
    {
        List<ModelForm> list = new ArrayList<ModelForm>();
        ModelForm  modelForm = new ModelForm();
        modelForm.setCount(1);
        modelForm.setName("aaaaa");
        list.add(modelForm);

        modelForm.setCount(2);
        modelForm.setName("ABABAAA");
        list.add(modelForm);

        modelForm.setCount(3);
        modelForm.setName("CACAAA");
        list.add(modelForm);

        model.addAttribute("list",list);
        System.out.print("4_okのlist_OKについて");
        System.out.print(list);
        return "thymeleaf/4_menu_ok";
    }

```
html
``` 4_menu_ok.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>4.繰り返しについて_OK</title>
</head>
<body>
コントロールからの値の取得に成功しました
<table>
    <thead>
    <tr>
        <th>count </th>
        <th>名前 </th>
    </tr>
    </thead>
    <tbody>
    <tr th:each="item : ${list}">
        <td th:text ="${item.count}"></td>
        <td th:text ="${item.name}"></td>
    </tr>>
    </tbody>>
</table>
nameは<div th:text="${list}" th:name="${list}"></div>


</body>
</html>
```

表示結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/3a104b46-f05b-9b7f-5fc4-a224ad68dfbb.png)


### NGな場合
model.addAttribute();の使い方について詰まりましたね

Controller
``` Controller.java
    @RequestMapping(value = "thymeleaf/4_menu", params = "NG", method = RequestMethod.POST)
    public String thymeleaf_4_menuNgController(Model model)
    {
        List<ModelForm> list = new ArrayList<>();
        ModelForm  modelForm = new ModelForm();
        modelForm.setCount(1);
        modelForm.setName("aaaaa");
        list.add(modelForm);

        modelForm.setCount(2);
        modelForm.setName("ABABAAA");
        list.add(modelForm);

        modelForm.setCount(3);
        modelForm.setName("CACAAA");
        list.add(modelForm);

        model.addAttribute(list);
        
        System.out.print("4_okのlist_NGについて");
        System.out.print(list);

        return "thymeleaf/4_menu_ng";
    }
```
html
``` 4_menu_ng.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>4.繰り返しについて_NG</title>
</head>
<body>
コントロールからの値の取得に失敗しました。
<table>
    <thead>
    <tr>
        <th>count </th>
        <th>名前 </th>
    </tr>
    </thead>
    <tbody>
    <tr th:each="item : ${list}">
        <td th:text ="{item.count}"></td>
        <td th:text ="{item.name}"></td>
    </tr>>
    </tbody>>
</table>
</body>
</html>
```


表示結果
Chromeの検証結果はスカスカになっていますね。
IDE側のデバッグじゃ確認できないのが手痛かったですね…
（Chromeの検証を使う習慣がなかった…）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/000885b7-0914-6aab-0fcd-034a079a7568.png)


# まとめ
IntelliJのデバッグ機能とChromeの検証機能両方使うと問題の突き止めが早いと分かりました。
私の場合は
１．IntelliJのデバッグモードでControllerを通っているか、値が入っているか確認
２．Chromeの検証機能で確認するようになりました。

# 参考資料
thymeleaf 公式ドキュメント
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf_ja.html

後悔しないためのSpring Boot 入門書：私が初めてthymeleaf触ったときに参考にした本です。

https://www.amazon.co.jp/%E5%BE%8C%E6%82%94%E3%81%97%E3%81%AA%E3%81%84%E3%81%9F%E3%82%81%E3%81%AESpring-Boot-%E5%85%A5%E9%96%80%E6%9B%B8%EF%BC%9ASpring-%E8%A7%A3%E4%BD%93%E6%96%B0%E6%9B%B8%EF%BC%88%E7%AC%AC2%E7%89%88%EF%BC%89-Spring%E8%A7%A3%E4%BD%93%E6%96%B0%E6%9B%B8-ebook/dp/B08XPBPH9C