0
votes

I am just starting to use thymeleaf for templating, and I am attempting to create a custom Processor for links

I want to be able to use a tag such as the below example to create custom links in my template:

<link rel="stylesheet" type="text/css" custom:href="/styles/main.css" />

The idea being that I have custom URLs on the site, so my custom processor will generate the correct URL for the relative link provided.

The above works fine - however, now I want to be able to include variables insite the value being passed to the processor - so have followed the example in the thymeleaf docs, and in the Processor, where I generate the replacement URL I have added the StandardExpression stuff:

    @Override protected String getTargetAttributeValue( Arguments arguments, Element element, String attributeName ){
need this to see if it can be factored out
        final Configuration configuration = arguments.getConfiguration()
        final IStandardExpressionParser parser = StandardExpressions.getExpressionParser(configuration)
        final String attributeValue = element.getAttributeValue(attributeName)
        final IStandardExpression expression = parser.parseExpression(configuration, arguments, attributeValue)
        final String relativeUrl = (String) expression.execute(configuration, arguments)

        urlService.generateUrl( relativeUrl )
    }

I was hoping that with this addition I would be able to also add links as follows:

<link rel="stylesheet" type="text/css" custom:href="/styles/${user.name}/main.css" />

(example not real, I'm not actually serving user based css :) - but you get the idea)

But that then breaks my first simple example, as the literal URL string is not an expression, to get around this I seem to have to also add single quotes to my URL so the expression parser knows its a string not a variable.

<link rel="stylesheet" type="text/css" custom:href="'/styles/main.css'" />

This seems really ugly, and probably error prone to have to repeat the single quotes in the simple cases (which will be the majority of the cases) - Is there a nicer way to do this? I'm hoping that as the expressions stuff is all curly braces based, there should be a way for the parser to recognise that anything outside of an of the valid expressions can be treated as strings?

(honestly, it has been a bit of a struggle to get my head around what is going on - the javadocs seem pretty sparse and there don't seem to be many examples - been a lot of trying to read the original source code to work out which classes I should use etc)

1

1 Answers

0
votes

This answer is after a long time, but will leave it here for anyone who stumbles upon this question.

Yout don't need a custom attribute provessor. Thymeleaf has a built in feature that will satisfy your requirements, which is the Link URL output expression (link to docs).

To output a static url write it like this:

<link ... th:href="@{/styles/main.css}" />

As the docs say, when you put / in front, the output URL will be context relative. So, if your site is deployed at /mysite, the attribute th:href="@{/styles/main.css}" will be converted to href="/mysite/style/main.css". If the site is deployed at root context, then the result will be href="/style/main.css".

The Link URL expression also includes support to insert url parameters like this:

<link ... th:href="@{/styles/main.css(un=${user.name})}"/>

The parameters are specified inside parentheses at the end of the url path. You can put multiple parameters separated by comas. The result of the above will be href="mysite/styles/main.css?un=rick", assuming user.name is rick.

If you want to insert the parameter into the path then write the following:

<link ... th:href="@{/styles/{un}/main.css(un=${user.name})}"/>

The {un} will be replaced by the value of ${user.name} without any parameters appended. So the result is:

<link ... href="mysite/styles/rick/main.css"/>

which is exactly what you need.

The syntax can seem complicated on first look. You should read the documentation carefully to understand it. The main point is that Thymeleaf has 3 types of curly braces:

  • ${...} for "variable expressions" as Thymeleaf docs call them. Which means for Spring EL expressions in your case, or for OGNL espressions in the standard dialect
  • #{...} is for localized message keys, and
  • @{...} is for Link URL output, which we covered here

You should read about these, and the whole Thymeleaf expression language in the docs. The localized message output also has its own special features like the url output.