1概要

このクイックチュートリアルでは、Thymeleafで

List

オブジェクトをバインドする方法を説明します。

ThymeleafとSpringを統合する方法を学ぶために、リンクをチェックすることができます:/thymeleaf-in-spring-mvc[ここの私達の主要な春の記事] – あなたはフィールドを表示する方法表示用データ


2 Thymeleafのリスト例

Thymeleafページに

List

の要素を表示する方法、およびThymeleafフォームでユーザーの入力としてオブジェクトのリストをバインドする方法を示すことから始めます。

そのために、次のコードに示す単純なモデルを使用します。

public class Book {
    private long id;

    private String title;

    private String author;

   //getters and setters
}

この例では既存の本を表示するだけでなく、ユーザーがコレクションに複数の本を追加したり、既存のすべての本を一度に編集したりできるようにします。


3リスト要素の表示


allBooks

ページを返す次の

Controller

メソッドを見てみましょう。

@GetMapping("/all")
public String showAll(Model model) {
    model.addAttribute("books", bookService.findAll());
    return "books/allBooks";
}

ここでは、ビューに送信されるモデル属性として

List

of

Book

オブジェクトを追加します。ここでは、HTMLテーブルを使用して表示します。

<table>
    <thead>
        <tr>
            <th> Title </th>
            <th> Author </th>
        </tr>
    </thead>
    <tbody>
    <tr th:if="${books.empty}">
            <td colspan="2"> No Books Available </td>
        </tr>
        <tr th:each="book : ${books}">
            <td><span th:text="${book.title}"> Title </span></td>
            <td><span th:text="${book.author}"> Author </span></td>
        </tr>
    </tbody>
</table>

ここでは、リスト全体を繰り返し処理し、その中の各オブジェクトのプロパティを表示するために、

th:each

プロパティを使用しています。


4選択式を使ったリストの束縛

フォーム送信を介してビューからコントローラにオブジェクトのリストを送信するために、

List

オブジェクト自体を使用することはできません。

代わりに、** 私たちは送信されたリストを保持するラッパーオブジェクトを追加する必要があります。

public class BooksCreationDto {
    private List<Book> books;

   //default and parameterized constructor

    public void addBook(Book book) {
        this.books.add(book);
    }

   //getter and setter
}

ユーザーが1つのフォーム送信で3冊の本を追加できるようにしましょう。

最初に、フォームオブジェクトを作成し、コマンドオブジェクトを

Model

属性として渡します。

@GetMapping("/create")
public String showCreateForm(Model model) {
    BooksCreationDto booksForm = new BooksCreationDto();

    for (int i = 1; i <= 3; i++) {
        booksForm.addBook(new Book());
    }

    model.addAttribute("form", booksForm);
    return "books/createBooksForm";
}

ご覧のとおり、3つの空の

Book

オブジェクトのリストをラッパークラス経由でビューに渡しました。

次に、Thymeleafページにフォームを追加する必要があります。

<form action="#" th:action="@{/books/save}" th:object="${form}"
  method="post">
    <fieldset>
        <input type="submit" id="submitButton" th:value="Save">
        <input type="reset" id="resetButton" name="reset" th:value="Reset"/>
        <table>
            <thead>
                <tr>
                    <th> Title</th>
                    <th> Author</th>
                </tr>
            </thead>
            <tbody>
                <tr th:each="book, itemStat : ** {books}">
                    <td><input th:field="** {books[____${itemStat.index}____].title}"/></td>
                    <td><input th:field="** {books[____${itemStat.index}____].author}"/></td>
                </tr>
            </tbody>
        </table>
    </fieldset>
</form>

そして、これは上のページがどのようになるかです:

リンク:/uploads/books-100×55.png%20100w[]

ここで行ったことを詳しく見てみましょう。最初に、コマンドオブジェクトを指定するために

th:object =” $ \ {form}”

を使用しました。

次に注目すべきことは、選択式を使ってリストにアクセスしたことです。

<tr th:each="book, itemStat : ** {books}">

そして最後に、__th:fieldを使用して、入力をリスト要素のプロパティとしてマッピングします。

ただし、参照するリスト要素を定義するには、

itemStat

変数を使用する必要もあります。

th:field="** {books[____${itemStat.index}____].title}"

最後のステップは、実際に送信されたデータをバックエンドで操作することです。コントローラの

@ PostMapping

メソッドでコマンドオブジェクトを

@ ModelAttribute

として使用し、取得した書籍のリストを保存して、既存の書籍をすべてユーザーに返します。

@PostMapping("/save")
public String saveBooks(@ModelAttribute BooksCreationDto form, Model model) {
    bookService.saveAll(form.getBooks());

    model.addAttribute("books", bookService.findAll());
    return "redirect:/books/all";
}

フォームを

/save

エンドポイントに送信すると、新しく追加されたすべての書籍のページが表示されます。

リンク:/uploads/allbooks-100×30.png%20100w[]


5変数式を使ったリストの束縛

この例では、まず既存のすべての本をコマンドオブジェクトにロードします。

@GetMapping("/edit")
public String showEditForm(Model model) {
    List<Book> books = new ArrayList<>();
    bookService.findAll().iterator().forEachRemaining(books::add);

    model.addAttribute("form", new BooksCreationDto(books));
    return "books/editBooksForm";
}

HTMLページは似ていますが、

th:each

ブロックで最も注目すべき違いがあります。

<tr th:each="book, itemStat : ${form.books}">
    <td>
        <input hidden th:name="|books[${itemStat.index}].id|" th:value="${book.getId()}"/>
    </td>
    <td>
        <input th:name="|books[${itemStat.index}].title|" th:value="${book.getTitle()}"/>
    </td>
    <td>
        <input th:name="|books[${itemStat.index}].author|" th:value="${book.getAuthor()}"/>
    </td>
</tr>


<tr th:each =” book、itemStat:$ \ {form.books}”>

に示すように、今回は変数式を使用して、少し異なる方法でリストにアクセスしました。特に適切なのは、** データを正しく送信するためにinput要素に

name



value

を提供したことに注意することです。

また、新しい本を作成するのではなく既存の本を編集したくないため、現在の本のIDをバインドする非表示の入力を追加する必要がありました。


6. 結論

この記事では、ThymeleafとSpring MVCで

List

オブジェクトを使用する方法を説明しました。ビューに送信されたオブジェクトのリストを表示する方法を示しましたが、Thymeleaf形式のリストとしてユーザー入力をバインドする2つの方法に主に焦点を当てています。

この記事に記載されているコードスニペットはすべてhttps://github.com/eugenp/tutorials/tree/master/spring-mvc-forms-thymeleaf[ourGitHub repository]にあります。