Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select Tag with Object - Thymeleaf and Spring MVC

I'm trying to change the code of this example thymeleafexamples-stsm, so I changed enum type for class type:

Type.java

public class Type { 

    private Integer id; 
    private String type; 
   ...getters and setters 
}

SeedStarterMngController.java

@ModelAttribute("allTypes") 
    public List<Type> populateTypes() { 
        Type type1 = new Type(); 
        type1.setId(1); 
        type1.setType("OUTDOOR"); 

        Type type2 = new Type(); 
        type2.setId(2); 
        type2.setType("INDOOR"); 

        List<Type> tipos = new ArrayList<Type>(); 
        tipos.add(type1); 
        tipos.add(type2); 
        return tipos; 
    } 

seedstartermng.html

<select th:field="*{type}">
    <option th:each="type : ${allTypes}" th:value="${type}" th:text="${type.type}">Wireframe</option>
</select>

So, I can't Add Seed Starter.

My Output html is

<select id="type" name="type">
    <option value="thymeleafexamples.stsm.business.entities.Type@2c08cec0">OUTDOOR</option>
    <option value="thymeleafexamples.stsm.business.entities.Type@26cf024">INDOOR</option>
</select>

and the error is

Failed to convert property value of type java.lang.String to required type thymeleafexamples.stsm.business.entities.Type for property type; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [thymeleafexamples.stsm.business.entities.Type] for property type: no matching editors or conversion strategy found

How I can do to be mapped to type correctly? I hope you can help me. Thank you.

like image 376
JohnPortella Avatar asked Aug 11 '14 00:08

JohnPortella


People also ask

Is Thymeleaf supported by Spring MVC?

Thymeleaf offers a set of Spring integrations that allow you to use it as a fully-featured substitute for JSP in Spring MVC applications.

How do I use the Thymeleaf th object?

We use th:action to provide the form action URL and th:object to specify an object to which the submitted form data will be bound. Individual fields are mapped using the th:field=”*{name}” attribute, where the name is the matching property of the object.

How do you pass parameters in Thymeleaf?

Request parameters can be easily accessed in Thymeleaf views. Request parameters are passed from the client to server like: https://example.com/query?q=Thymeleaf+Is+Great! In the above example if parameter q is not present, empty string will be displayed in the above paragraph otherwise the value of q will be shown.

Is Thymeleaf outdated?

While Thymeleaf is more of a template engine for server-side application development. But Thymeleaf's popularity is on a steady rise. The developer community is slowly moving away from 'once a common' MVC framework for Javascript-based development.


1 Answers

I know this question is old but below answer may help someone as I could not find it easily.

To solve this issue, Thymeleaf uses Formatters to convert between Object and String.

  • In display phase (GET), Formatter Service will convert Object to String.
  • In submitting phase (POST), Formatter Service will convert String back to

    object.

First implement Formatter service for your Class to be used in tag:

@Service
public class TypeFormatter implements Formatter<Type> {

    @Autowired
    TypeService typeService;//Service -> DB

    @Override
    public String print(Type object, Locale locale) {
        return (object != null ? object.getId().toString() : "");
    }

    @Override
    public Type parse(String text, Locale locale) throws ParseException {
        Integer id = Integer.valueOf(text);
        return this.typeService.get(id);//return Type object form DB
    }
}

It is very simple class with two methods:

  • print: converts object to string.
  • parse: converts string to object.

Now, we've to tell Spring-Thymeleaf abbout our formatter or we may call it converter. To do that we've to register this formatter in our WebConfig (Configuration class whic extends WebMvcConfigurerAdapter):

@Configuration
@EnableWebMvc
@ComponentScan(value = { "your package" })
public class WebConfig extends WebMvcConfigurerAdapter {

....
    //Formatters

    @Autowired //Without autowire, this solution may not work
    private TypeFormatter typeFormatter;

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(typeFormatter);
    }
}

Now our solution is ready to be implemented in html file but how to tell Thymeleaf to apply conversion? Answer is by using th:field="*{type}" attribute and using Double-bracket syntax th:value="${{type}}":

<select th:field="*{type}">
    <option th:value="NULL" th:text="---Select Type---"></option>
    <option th:each="type : ${allTypes}" th:value="${{type}}" th:text="${type.type}">Wireframe</option>
</select>
  • th:field="*{type}" is applying registered Formatter service by default. It will convert type to String (here the string will be Type Id)
  • th:value="${{type}}" is converting type to string as well.
  • In submit, Spring will use the Formatter service to convert Id back to object.

Last thing to tell, sometimes we want to add a header to the dropdown list like "-----Select Type-----" in order to prevent default selection as well as explain to user. In this case you must set th:value="NULL" unless you'll get conversion error.

like image 54
Ayman Al-Absi Avatar answered Nov 27 '22 13:11

Ayman Al-Absi