inanutshellus
inanutshellus

Reputation: 10001

Nested Thymeleaf Templates in Spring

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?

Upvotes: 1

Views: 3927

Answers (1)

Faraj Farook
Faraj Farook

Reputation: 14875

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}" and th:object="${order.customer.mailingAddress}" outside each import.

Upvotes: 1

Related Questions