I am building an application using Spring, Hibernate and of course Thymeleaf for the views. The application is centered around an Activity domain class (which is literally an in- or outdoor activity organized by a club member). The class has several lookup fields (category region) which are modelled as domain classes mapped by Hibernate to database lookup tables.
In the Edit view page I show a dropdown box to be able to choose a lookup value, also the current value must be shown using the selected attribute. Here it goes wrong. The select attribute is never generated although the boolean expression appears to be correct.
The th:attr is added to show the values of the compared expressions, namely ${choice.id} and *{category.id} Those values are correct. I added the readonly attribute (not suitable for a select element but just to chech whether it could be a problem of the th:selected attribute) and we see in the output that this attribute IS generated in the output!
<label>Categorie</label>
<select th:field="*{category}">
<option th:each="choice : ${allCategories}"
th:value="${choice.id}"
th:attr="choiceid=${choice.id}, categoryid=*{category.id}, showselected=(${choice.id} == *{category.id})"
th:selected="(${choice.id} == *{category.id})"
th:readonly="(${choice.id} == *{category.id})"
th:text="${choice.description}"></option>
</select>
HTML output:
<label>Categorie</label>
<select id="category" name="category">
<option choiceid="1" categoryid="2" showselected="false" value="1">Actief en sportief</option>
<option choiceid="2" categoryid="2" showselected="true" readonly="readonly" value="2">Uitgaan en nachtleven</option>
<option choiceid="3" categoryid="2" showselected="false" value="3">Kunst en cultuur</option>
<option choiceid="4" categoryid="2" showselected="false" value="4">Eten en drinken</option>
<option choiceid="5" categoryid="2" showselected="false" value="5">Ontspanning en gezelligheid</option>
</select>
So my questing boils down to: why is selected="selected"
not generated for option element with id=2?
Of course it can be achieved by generating is with an th:attr expression but according to the documentation it should just work in this way.
Also I tried to bypass the use of the special th:selected attribute and use th:attr to generate the selected attribute for the selected option (the value 'none' is temporary used for clarity'):
th:attr="selected=(${choice.id} == *{category.id}) ? 'selected' : 'none'"
Again, nothing is shown and no selected attribute is rendered. I tried to repeat is with a custom attribute name (the Dutch translation of the word selected, of course unknown to Thymeleaf):
th:attr="geselecteerd=(${choice.id} == *{category.id}) ? 'selected' : 'none'"
And now it is rendered! See the output below:
<select id="category" name="category">
<option geselecteerd="none" value="1">Actief en sportief</option>
<option geselecteerd="selected" value="2">Uitgaan en nachtleven</option>
<option geselecteerd="none" value="3">Kunst en cultuur</option>
<option geselecteerd="none" value="4">Eten en drinken</option>
<option geselecteerd="none" value="5">Ontspanning en gezelligheid</option>
</select>
I am really lost now, the selected attribute is perfectly legal and the only choice here but it appears that Thymeleaf is ignoring it. How to solve this?