Thymeleaf模板字符串拼接异常:option值未正确生成问题
${item.id}-${driver.id} Looks like your Thymeleaf expression for joining item.id and driver.id isn’t behaving as expected—you’re getting "-2" which means item.id is resolving to an empty value (or null) while driver.id correctly picks up 2. Let’s break down the problem and fix it:
Why This Happens
Your original expression th:value="${item.id}-${driver.id}" gets parsed as two separate expressions with a hyphen stuck in between. If item.id is null or fails to resolve, Thymeleaf converts it to an empty string, leaving you with "" + "-" + "2" = "-2".
Solutions to Correct the Concatenation
Here are three reliable ways to fix the string joining in Thymeleaf:
1. Use Thymeleaf’s String Concatenation Operator (+)
Explicitly tell Thymeleaf to treat this as a string concatenation operation:
<tr th:each="item: ${devices}" > <td class="col_id" th:text="${item.id}" ></td><!-- ID --> <td class="col_name" th:text="${item.description}"></td><!-- NAME --> <td class="col_name" th:if="${#authorization.expression('hasRole(''ROLE_ADMIN'')')}" th:text="${item.application.name}"></td><!-- NAME --> <td class="col_name" > <select id="selectAuthorizedDriverId" > <option th:each="driver : ${drivers}" th:value="${item.id + '-' + driver.id}" th:text="${driver.firstName}" th:selected="${driver.id == item.driverDevices[0].driver.id}" > </option> </select> </td> </tr>
2. Use Thymeleaf Inline Text Syntax (|...|)
This is a cleaner, more readable way to concatenate variables into strings, and it handles nulls more predictably:
<tr th:each="item: ${devices}" > <td class="col_id" th:text="${item.id}" ></td><!-- ID --> <td class="col_name" th:text="${item.description}"></td><!-- NAME --> <td class="col_name" th:if="${#authorization.expression('hasRole(''ROLE_ADMIN'')')}" th:text="${item.application.name}"></td><!-- NAME --> <td class="col_name" > <select id="selectAuthorizedDriverId" > <option th:each="driver : ${drivers}" th:value="|${item.id}-${driver.id}|" th:text="${driver.firstName}" th:selected="${driver.id == item.driverDevices[0].driver.id}" > </option> </select> </td> </tr>
3. Handle Null Values for item.id
If there’s a chance item.id could be null, add a fallback to avoid unexpected hyphens:
<tr th:each="item: ${devices}" > <td class="col_id" th:text="${item.id}" ></td><!-- ID --> <td class="col_name" th:text="${item.description}"></td><!-- NAME --> <td class="col_name" th:if="${#authorization.expression('hasRole(''ROLE_ADMIN'')')}" th:text="${item.application.name}"></td><!-- NAME --> <td class="col_name" > <select id="selectAuthorizedDriverId" > <option th:each="driver : ${drivers}" th:value="${#strings.defaultString(item.id, '') + '-' + driver.id}" th:text="${driver.firstName}" th:selected="${driver.id == item.driverDevices[0].driver.id}" > </option> </select> </td> </tr>
Additional Checks
- First, verify that
${item.id}is actually populated: The<td class="col_id" th:text="${item.id}"></td>should render the correct ID value. If it’s empty here, the issue is with yourdeviceslist not having valididvalues, not the concatenation. - Ensure the
itemvariable is in scope for the<option>tag: Since your<select>is inside theth:each="item: ${devices}"loop,itemshould be accessible, but if you have nested loops or scope issues, try storing the ID in a local variable withth:with:<tr th:each="item: ${devices}" th:with="deviceId=${item.id}" > <!-- ... --> <option th:each="driver : ${drivers}" th:value="${deviceId + '-' + driver.id}" <!-- ... --> ></option> </tr>
内容的提问来源于stack exchange,提问作者Nunyet Calçada

