Select Tag with Object - Thymeleaf and Spring MVC

后端 未结 2 1818
梦如初夏
梦如初夏 2021-01-02 14:21

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 { 

    p         


        
相关标签:
2条回答
  • 2021-01-02 14:48

    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.

    0 讨论(0)
  • 2021-01-02 14:53

    That error message basically says Spring don't know how to convert the string thymeleafexamples.stsm.business.entities.Type@2c08cec0 into an instance of Type. This is a bug on your code because it doesn't make any sense trying to do so.

    You're not supposed to use the toString() value of Object as a form dropdown identifier. You need to have a (much) better strategy for the code to identify the Type selected by user.

    Common approach is to use the id attribute:

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

    When the form is submitted, you then need to retireve an instance of Type based on its id name on your controller

    0 讨论(0)
提交回复
热议问题