Search code examples
spring-bootthymeleaf

Thymeleaf fragment: passing form field name as parameter


I'm trying to extract a form input as a page fragment in my Spring Boot + Thymeleaf application.

I'm doing something like this:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>form controls</title>
</head>
<body>
<div class="form-group" th:fragment="text-input (fieldName, fieldLabel)">
    <label th:text="${fieldLabel}">label</label>
    <input th:field="*{${fieldName}}" type="text" class="form-control"/>
    <div th:if="${#fields.hasErrors('${fieldName}')}">
        <span th:errors="*{${fieldName}}" class="text-danger"></span>
    </div>
</div>
</body>
</html>

And I'm using the fragment this way:

<div th:replace="form-controls :: text-input (fieldName='firstName', fieldLabel='Name')">

But I'm getting this error:

org.springframework.beans.NotReadablePropertyException: Invalid property '${fieldName}' of bean class [my.app.Dto]: Bean property '${fieldName}' is not readable or has an invalid getter method

So the parameter fieldName is not resolved correctly...

Is there something wrong in my code? Is it possible to implement something similar to my fragment in Thymeleaf?


Solution

  • The solution to my issue was: Thymeleaf expression preprocessing.

    Preprocessing is an execution of the expressions done before the normal one that allows for modification of the expression that will eventually be executed.

    So, to fix fieldName resolution I had to surround every ${fieldName} exp with a double underscore:

    <div class="form-group" th:fragment="text-input (fieldName, fieldLabel)">
        <label th:text="${fieldLabel}">label</label>
        <input th:field="*{__${fieldName}__}" type="text" class="form-control"/>
        <div th:if="${#fields.hasErrors(fieldName)}">
            <span th:errors="*{__${fieldName}__}" class="text-danger"></span>
        </div>
    </div>