Привязка списка в 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. Отображение элементов списка

Давайте посмотрим на следующий методController, который возвращает страницуallBooks:

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

Здесь мы добавилиList изBook объектов в качестве атрибута модели, отправляемого в представление, где мы будем отображать его с помощью таблицы 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
}

Теперь давайте позволим пользователю добавить три книги за одну отправку формы.

Сначала мы подготовим страницу формы, передав наш командный объект как атрибут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 object (тот, который мы передали как атрибутModel).

Следующее, что стоит отметить, это то, что мы получили доступ к списку с помощью выражения выбора, используя:

И наконец,we’re mapping our inputs as properties of the list elements using th:field.

Однако нам также необходимо использовать переменнуюitemStat, чтобы определить, какой элемент списка мы имеем в виду, как показано в:

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

Последний шаг на самом деле манипулировать представленные данные на серверной части. Мы будем использовать объект команды в качестве@ModelAttribute в нашем методе@PostMapping в контроллере, сохраним полученный список книг и вернем все существующие книги пользователю:

@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.

Нам также пришлось добавить скрытый ввод, который привяжет идентификатор текущей книги, потому что мы не хотим создавать новые книги, а редактировать существующие.

6. Заключение

В этой статье мы показали, как использовать объектList в Thymeleaf и Spring MVC. Мы показали, как отобразить список объектов, отправленных в представление, но мы сосредоточили основное внимание на двух способах привязки вводимых пользователем данных в виде списка в форме Thymeleaf.

Все фрагменты кода, упомянутые в статье, можно найти вour GitHub repository.