Search code examples
javahtmlspringthymeleafdropdown

Dynamic Thyemeleaf field setter for fragment


I would like to create a fragment of a dropdown in this case, and would like to make it, so other custom objects can use it. It should make more sense in code form:

Dropdown Fragment:

 <body th:fragment="dropdownSearch(field)">
   <div class="select is-normal">
     <input list="browsers" name="browser" th:field="*{field}">
     <datalist id="browsers">
       <option th:each="i : ${#numbers.sequence(0, __${valuesDataIndexSize - 1}__)}" 
        th:value="${i}" th:text="${i} + ' - Kommentar'"></option>
     </datalist>
   </div>
 </body>

Fragment call example

<div th:replace="fragments/dropdown.html :: dropdownSearch(field=*{projectOptions.zMatrixIndex})"></div>

The goal here is to make the th:field in the dropdown fragment dynamic so as seen in the fragment call example, it can be set to be custom, which in this case should be projectOptions.zMatrixIndex. So if I call the fragment and tell it, that field should be test, it should set the th:field in the fragment to th:field="*{test}".

If I execute the code as it is now, I receive this error:

2022-09-22 15:57:39.818 ERROR 5516 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    
: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception 
[Request processing failed; nested exception is 
org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 
'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: 
"fragments/dropdown.html" - line 8, col 41)] with root cause

org.springframework.beans.NotReadablePropertyException: Invalid property 'field' of bean class 
[com.tribus.tribusspring.entities.objects.project.main.ProjectData]: Bean property 'field' is 
not readable or has an invalid getter method: Does the return type of the getter match the 
parameter type of the setter?

Thank you for any help!


Solution

  • You can't pass references to objects when using th:field instead, you have to pass the string name of the object and then use preprocessing. Like this:

    <div th:replace="fragments/dropdown.html :: dropdownSearch(field='projectOptions.zMatrixIndex')"></div>
    

    and then

    <input list="browsers" name="browser" th:field="*{__${field}__}">
    

    (it's just how th:field works.)