Short version
How is one supposed to make nested templates in Thymeleaf when using Spring? It appears asterisk notation is not supported ("*{mailingAddress}"
) inside th:object
attributes in Spring. Is there a work-around / different tag to use?
Long version
For example, let's say I have these classes:
class Address { String street; }
class Person { Address mailingAddress; Address shippingAddress; }
class Order { int orderNo; Person customer; }
So I make an address.html
Thymeleaf template:
<span th:text="*{street}"></span>
We test it with a sample Address
. Looks good.
and I make a person.html
Thymeleaf template that references the address like so:
<span th:text="*{firstName}"></span>
<span th:object="${person.shippingAddress}">
<span th:include="fragments/address :: address"></span>
</span>
And we test it with an example person. I could even reference the same template and set the context to be the ${person.mailingAddress}
. So far so good.
Now let's make our Order
template. Only, hey, wait. Earlier, in our person.html
file we said ${person.shippingAddress}
but now we need it to say ${order.customer.shippingAddress}
. If I were not using Spring I'd put the following into person.html
:
<span th:text="*{firstName}"></span>
<span th:object="*{shippingAddress}">
<span th:include="fragments/address :: address"></span>
</span>
That way, no matter what my path to getting here all I have to care about is that my current context has a shippingAddress
. I could then use person.html
directly as well as within my order.html
template.
Unfortunately I am in Spring, so I get the following exception:
org.thymeleaf.exceptions.TemplateProcessingException:
The expression used for object selection is *{shippingAddress},
which is not valid: only variable expressions (${...}) are
allowed in 'th:object' attributes in Spring-enabled environments.
(include:510)
at org.thymeleaf.spring4.processor.attr.SpringObjectAttrProcessor.validateSelectionValue(SpringObjectAttrProcessor.java:73)
at org.thymeleaf.standard.processor.attr.AbstractStandardSelectionAttrProcessor.getNewSelectionTarget(AbstractStandardSelectionAttrProcessor.java:69)
at org.thymeleaf.processor.attr.AbstractSelectionTargetAttrProcessor.processAttribute(AbstractSelectionTargetAttrProcessor.java:61)
To move forward I must duplicate all my nested templates. In this example, I would have one person.html
with th:object="${person.mailingAddress}"
calling to address.html
, and a duplicate of person.html
called orderCustomer.html
where we change the line to th:object="${order.customer.mailingAddress}"
, but is otherwise identical.
Is there a work-around out there that would let me re-use templates?
You can report a bug to the thymeleaf developers in github, or fork the project to add this functionality and convince the Daniel Fernández to accept it.
https://github.com/thymeleaf/thymeleaf/issues
Or else, he is available in StackOverflow. You can simply send him a message about the posibility of integrating this functionality
https://stackoverflow.com/users/550664/daniel-fern%C3%A1ndez
apart from that there is nothing much we can do rather to stick with the approach of putting
th:object="${person.mailingAddress}"
andth:object="${order.customer.mailingAddress}"
outside each import.