Thymeleafでリストをバインドする

Thymeleafでリストをバインドする

1. 概要

このクイックチュートリアルでは、how to bind a List object in Thymeleafを表示します。

ThymeleafをSpringと統合する方法については、our main Spring article hereを確認してください。ここでは、フィールドの表示、入力の受け入れ、検証エラーの表示、または表示用のデータの変換の方法も学習できます。

2. Thymeleafの例のリスト

まず、how to display elements of a List in a Thymeleaf page and how to bind a list of objects as user’s inputs in a Thymeleaf formを表示します。

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

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";
}

ここでは、ビューに送信されるモデル属性としてBookオブジェクトのListを追加しました。ここでは、HTMLテーブルを使用して表示します。

Title Author
No Books Available
Title Author

ここでは、we’re using the th:each property to iterate through the listとその中の各オブジェクトのプロパティを表示します。

4. 選択式を使用したリストのバインド

フォーム送信を介してビューからコントローラーにオブジェクトのリストを送信するために、Listオブジェクト自体を使用することはできません。

代わりに、we have to add a wrapper object that will hold the submitted list:

public class BooksCreationDto {
    private List 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ページにフォームを追加する必要があります。

Title Author

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

image

ここで行ったことを詳しく見てみましょう。 まず、we used the th:object=”${form}” to specify the command objectModel属性として渡したもの)。

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

そして最後に、we’re mapping our inputs as properties of the list elements using 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エンドポイントに送信すると、新しく追加されたすべての書籍が記載されたページが表示されます。

image

5. 変数式を使用したリストのバインド

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

@GetMapping("/edit")
public String showEditForm(Model model) {
    List 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}”>に示すように、今回は変数式を使用して、少し異なる方法でリストにアクセスしました。 特に関連するのはnotice that we provided name and value for input elements to properly submit dataです。

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

6. 結論

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

記事に記載されているすべてのコードスニペットは、our GitHub repositoryにあります。