Search code examples
springthymeleaf

Thymeleaf: `th:value` in option is getting split at "," resulting in two values instead of one


I have a list of states including:

  • germany
  • iran, islamic republic
  • england
  • ....

I put this list into a multiple selection input:

<select th:field="*{statesSelection}" multiple="multiple">
  <option
    th:each="state : ${states}"
    th:value="${state}"
    th:text="${state}"></option>
</select>

The ui element renders correctly and also the source inspection of the browser shows me that everything is correctly set.

The java data transfer object:

public class Selection implements Serializable {
    ...
    private List<String> statesSelection = new ArrayList<>();
    ...
}

And the actual endpoint:

@RequestMapping(value = "/select")
public String select(Model model, @ModelAttribute Selection selection) {

}

The Problem

After I selected iran, islamic republic and press submit, the endpoint does not get a list with a single entry iran, islamic republic it is getting a list of two entries: iran and islamic republic so the value is getting split up at ,.

How can I prevent that from happening?

EDIT

I just realized that the problem only occurs if iran, islamic republic is the only value that I select. As soon as I select a second value together with iran the problem does not occur.


Solution

  • So I tried to use the following:

    <select th:field="*{statesSelection}" multiple="multiple">
      <option
        th:each="state : ${states}"
        th:value="${#uris.escapePath(state)}"
        th:text="${state}"></option>
    </select>
    

    But that resulted in the following: iran, %20islamic%20republic which in the backend resulted in:

    • iran
    • %20islamic%20republic

    So to things:

    1. It does not get automatically url encoded / decoded.
    2. Value is still splitted.

    I found a solution for the problem:

    1. I URL encode all values in the backend
    2. Send them to the frontend
    3. URL decode the values in the label text
    4. Send selected values to the backend
    5. URL Decode values in the backend
    <select th:field="*{statesSelection}" multiple="multiple">
      <option
        th:each="state : ${states}"
        th:value="${state}"
        th:text="${#string.replace(#uris.unescapePath(state), '+', ' ')}"></option>
    </select>
    

    I need to replace + with because java URL Encoder is encoding spaces to the + symbol.