Thymeleaf returning a String array instead of List<Object>

spring boot thymeleaf checkbox example
thymeleaf multiple checkbox spring mvc
thymeleaf checkbox binding

I am learning how to use Spring Boot and Thymeleaf. I have an issue where I provide a list of a specific Objects in the Form List to the a Thymeleaf page. When the user selects the values and posts the results, the result is a String of the selected objects and incompatible with the Object I wanted to store the values in.

This may sound like a mouthful so below is the code.

My question is: Is there anyway to ensure that Thymeleaf returns a List of Objects?

Input: A class passes a bunch of Ingredients to the form This class passes in a List of class Ingredient to the form (The filtering does not matter for this - A list is inserted as the value of the model attribute, with the key being a type of ingredient)

@GetMapping
public String showDesignForm(Model model) {
    List<Ingredient> ingredients = new ArrayList<>();
    ingredientRepo.findAll().forEach(i -> ingredients.add(i));  
    Type[] types = Ingredient.Type.values();
    for (Type type : types) {
        model.addAttribute(type.toString().toLowerCase(), filterByType (ingredients, type));
    }   
    model.addAttribute("taco", new Taco()); 
    return "design";
}

Thymeleaf takes that list and displays it in checkboxes

<!DOCTYPE html>
<html
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Taco Cloud</title>
<link rel="stylesheet" th:href="@{/styles.css}" />
</head>
<body>
<h1>Design your taco!</h1>
<img th:src="@{/images/TacoCloud.png}"/>
<form method="POST" th:object="${taco}">
<div class="grid">
<div class="ingredient-group">
<h3>Designate your wrap:</h3>
<div th:each="ingredient : ${wrap}">
<input name="ingredients" type="checkbox" th:value="${ingredient}" />
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
<div class="ingredient-group">
<h3>Pick your protein:</h3>
<div th:each="ingredient : ${protein}">
<input name="ingredients" type="checkbox" th:value="${ingredient}" />
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
<div class="ingredient-group">
<h3>Choose your cheese:</h3>
<div th:each="ingredient : ${cheese}">
<input name="ingredients" type="checkbox" th:value="${ingredient}" />
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
<div class="ingredient-group">
<h3>Determine your veggies:</h3>
<div th:each="ingredient : ${veggies}">
<input name="ingredients" type="checkbox" th:value="${ingredient}" />
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
<div class="ingredient-group">
<h3>Select your sauce:</h3>
<div th:each="ingredient : ${sauce}">
<input name="ingredients" type="checkbox" th:value="${ingredient}" />
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
</div>
<div>
<h3>Name your taco creation:</h3>
<input type="text" th:field="*{name}"/>
<br/>
<button>Submit your taco</button>
</div>
</form>
</body>
</html>

Destination class: Expects the returned value to be List

package tacos;

import java.util.Date;
import java.util.List;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import lombok.Data;

@Data
public class Taco {

    private Long id;

    private Date createdAt;

    @NotNull
    @Size(min=5, message="Name must be at least 5 characters long")
    private String name;
    @Size(min=1, message="You must choose at least 1 ingredient")
    private List<Ingredient> ingredients;
}

Error:

Field error in object 'taco' on field 'ingredients': rejected value [Ingredient(id=FLTO, name=Flour Tortilla, type=WRAP),Ingredient(id=CHED, name=Cheddar, type=CHEESE)]; codes [typeMismatch.taco.ingredients,typeMismatch.ingredients,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [taco.ingredients,ingredients]; arguments []; default message [ingredients]]; default message [Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.List' for property 'ingredients'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'tacos.Ingredient' for property 'ingredients[0]': no matching editors or conversion strategy found]

I encountered same problem in some code but I overcame it through using Spring JPA. But If you were using other than Spring JPA, you could use this converter for your application. According to your code, property id of Ingredient is String. So code will be.

@Component
public class IngredientConverter implements Converter<String, Ingredient> {

private final IngredientRepo ingredientRepo;

@Autowired
public IngredientConverter(IngredientRepo ingredientRepo) {

    this.ingredientRepo = ingredientRepo;
}

@Override
public Ingredient convert(String source) {

      List<Ingredient> ingredients = new ArrayList<>();

      ingredientRepo.findAll().forEach(i -> ingredients.add(i));

      for (Ingredient ingredient : ingredients) {

        // You may use equal() method
        if (ingredient.getId() == source)

            return ingredient;
      }

      return null;
   }

}

Working With Arrays in Thymeleaf, Learn how to use arrays in the Thymeleaf template engine. public String arrayController(Model model) { return "continents" ; keyword to iterate over the element of an array, we're not restricted to using list tags only. In this article, we've explored one of many features provided by the Thymeleaf library. We presented iteration in Thymeleaf by using the attribute th:each, along with its out-of-the-box properties. A working version of the code shown in this article is available in our GitHub repository.

I came across a video which helped create a converter between the String result of the Thymeleaf page and the POST method in Spring.

https://www.youtube.com/watch?v=e9mlrHyn73w&t=627s

How to Save Changes made to an array within Thymeleaf?, return this.name; public String readCNFG(Model model, @RequestParam String cnfgListId) { rather you should have that array as a property on a command object.) public void setFitList(ArrayList<People> peopleList){ When the user selects the values and posts the results, the result is a String of the selected objects and incompatible with the Object I wanted to store the values in. This may sound like a mouthful so below is the code. My question is: Is there anyway to ensure that Thymeleaf returns a List of Objects?

You should change private List<Ingredient> ingredients; as private List<String> ingredients;

16 Template Cache, public class ProductService { public List<Product> findAll() { return ProductRepository. Templates are resolved by String name (​templateProcessingParameters. #aggregates : utility methods for creating aggregates on arrays or collections. executed by OGNL instead of the Thymeleaf Standard Expression engine): For this article i will focus on all the core HTML Form Elements, how to render them with HTML+Thymeleaf and the data/interaction integration between Spring Boot and Thymeleaf. Here is the code

Thymeleaf template mode, public class ProductService { public List<Product> findAll() { return ProductRepository. for attribute names and hyphen ( - ) separators instead of semi-colons ( : ): <! We have added a String variable called today to our context​, and to arrays or collections is also performed with brackets, * writing the  Java 8 provides an extremely powerful abstract concept Stream with many useful mechanics for consuming and processing data in Java Collection. In the tutorial, We will use lots of examples to explore more the helpful of Stream API with filtering function on the specific topic: “Filter Collection with Java 8 Stream”.

How to get the last element of Arraylist?, List; public class ArrayListExample { public static void main(String[] args) { /* Creating ArrayList of Strings and adding * elements to it */ List<String> al = new  Preface. This tutorial explains how Thymeleaf can be integrated with the Spring Framework, especially (but not only) Spring MVC. Note that Thymeleaf has integrations for both versions 3.x and 4.x of the Spring Framework, provided by two separate libraries called thymeleaf-spring3 and thymeleaf-spring4.

Thymeleaf Utility Objects · GitHub, #strings: utility methods for String objects: contains, startsWith, prepending/​appending, etc. #objects: See javadoc API for class org.thymeleaf.expression.​Dates Also works with arrays, lists or sets. */ Null is returned instead of a default. To learn more about how to use Thymeleaf with Spring Boot, check out this tutorial. Before we discuss how conditionals work in Thymeleaf, let us first define a simple model class named User.java that we will use throughout the article: User.java

Comments
  • good answer but is this really necessary? this will require so much code :/ there must be another way.