Thymeleaf和SpringBoot的下拉列表

时间:2016-02-29 14:20:36

标签: spring-mvc spring-boot thymeleaf

我有一个在HTML上使用Thymeleaf的Spring Boot 1.3应用程序。我有用户页面,当我编辑它们时,我希望从列表中选择用户机构。我让窗口正确显示所有内容,但是当我选择机构时,控制器不显示所选值。

这是我的HTML:

 <div class="form-group">
     <label class="col-md-3 control-label">Institution</label>
         <div class="col-md-5">
         <div th:if="${institutionList != null and not #lists.isEmpty(institutionList)}">
             <select>
                 <option th:each="dropDownItem : ${institutionList}"
                                 th:value="${dropDownItem.name}"
                                 th:text="${dropDownItem.name}" />
             </select>
        </div>
        <div th:if="${institutionList == null or lists.isEmpty(institutionList)}">
            <div>"No Institutions were found, please create some first"</div>
        </div>
    </div>
 </div>

这是我的控制器

@Controller
@PreAuthorize("hasRole('Admin')")
@RequestMapping("/admin")
public class AdminController {
    @Transactional
    @PreAuthorize("hasRole('ADMIN')")
    @RequestMapping(value = "/addUser", method = RequestMethod.POST)
    public String checkPersonInfo(@ModelAttribute User user, Model model, Authentication authentication) {
        // user does not have the selected institution set
        customUserDetailsService.createNewUser(user);
        updateModelWithAllUsers(model);
        return "admin";
    }

    private void updateModelWithAllUsers(Model model) {
        model.addAttribute(USERLIST, customUserDetailsService.findAllUsers());
        model.addAttribute(INSTITUTION_LIST, institutionService.findAll());
        model.addAttribute("user", new User());
    }

...
}

这是我的用户:

@Entity
@Table(name = "Users")
public class User implements UserDetails {
 @Id
    private String username;

    @Column(nullable = false)
    private String password;

    private boolean enabled;
    private boolean accountNonExpired;
    private boolean accountNonLocked;
    private boolean credentialsNonExpired;
    private String companyName;
    private String email;

    @ElementCollection(fetch=FetchType.EAGER)
    @CollectionTable(name="Authorities", joinColumns=@JoinColumn(name="username"))
    @Column(name="authority")
    private Set<String> roles = new HashSet<String>();

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "institutionId", nullable = false)
    private Institution institution;
... getters & setters
}

我的机构:

@Entity
@Table(name = "Institution")
public class Institution {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long institutionId;
    private String name;

    @OneToMany(mappedBy = "institution", fetch = FetchType.EAGER)
    @Fetch(value = FetchMode.SUBSELECT)
    List<User> users = new ArrayList<User>();
    ... getters & setters
}

当&#34; / addUser&#34;从UI获取User对象,该机构为空。

EDIT 我使用Sergios建议来使用select th:field="${user.institution}"以及select th:field="*{institution}"

但这给了我一个错误:

  

org.springframework.validation.BeanPropertyBindingResult:1个错误   对象&#39;用户&#39;中的字段错误在现场&#39;机构&#39;:被拒绝的价值   [com.security.Institution@3e3945d2];代码   [typeMismatch.user.institution,typeMismatch.institution,typeMismatch.com。   .security.Institution,typeMismatch];参数   [org.springframework.context.support.DefaultMessageSourceResolvable:   代码[user.institution,institution];参数[];默认消息   [机构]];默认消息[无法转换属性值   type&#39; java.lang.String&#39;要求的类型&#39; com.security.Institution&#39;   对于财产&#39;机构&#39 ;;嵌套异常是   org.springframework.core.convert.ConversionFailedException:失败   从类型java.lang.String转换为类型java.lang.Long的值   &#39; com.security.Institution@3e3945d2' ;;嵌套异常是   java.lang.NumberFormatException:对于输入字符串:&#34; com。   .security.Institution @ 3e3945d2&#34;]

不确定我是否正确阅读此内容,但这是否意味着Thymeleaf正在尝试将Institution.name传递给user.institution字段?

有人可以就如何做到这一点提出任何建议吗?

1 个答案:

答案 0 :(得分:5)

您已忘记指明必须从中获取所选值的字段:

示例:我支持User类具有机构的属性。

<div class="form-group">
 <label class="col-md-3 control-label">Institution</label>
     <div class="col-md-5">
     <div th:if="${institutionList != null and not #lists.isEmpty(institutionList)}">
         <select th:field="*{institution}">
             <option th:each="dropDownItem : ${institutionList}"
                             th:value="${dropDownItem.name}"
                             th:text="${dropDownItem.name}" />
         </select>
    </div>
    <div th:if="${institutionList == null or lists.isEmpty(institutionList)}">
        <div>"No Institutions were found, please create some first"</div>
    </div>
</div>

更多信息:http://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#dropdownlist-selectors

编辑: 您需要向您的应用程序指明如何将表单(字符串类型)中返回的Insitution ID转换为Institution实体。为此,你必须使用转换器。

首先将选项的值更改为institutionId:

<div class="form-group">
 <label class="col-md-3 control-label">Institution</label>
     <div class="col-md-5">
     <div th:if="${institutionList != null and not #lists.isEmpty(institutionList)}">
         <select th:field="*{institution}">
             <option th:each="dropDownItem : ${institutionList}"
                             th:value="${dropDownItem.institutionId}"
                             th:text="${dropDownItem.name}" />
         </select>
    </div>
    <div th:if="${institutionList == null or lists.isEmpty(institutionList)}">
        <div>"No Institutions were found, please create some first"</div>
    </div>
</div>

您必须创建一个实现Converter接口的类。

@Component
public class StringToInstitution implements Converter<String, Institution> {

@Autowired
private InstitutionRepository repository; //Or the class that implments the repository.

    @Override
    public Institution convert(String arg0) {
        Long id = new Long(arg0);
        return repository.findOne(id);
    }

}