Home > Back-end >  Render dynamic tag name with Thymeleaf
Render dynamic tag name with Thymeleaf

Time:06-22

Is there a way to render a tag with a tag name that is not constant in the template? I want to produce a heading tag h1, h2, ..., or h6 depending on some attribute of the page model like in the following template:

<h1 th:text="${model.title}" th:if="${model.level == 1}"></h1>
<h2 th:text="${model.title}" th:if="${model.level == 2}"></h2>
<h3 th:text="${model.title}" th:if="${model.level == 3}"></h3>
<h4 th:text="${model.title}" th:if="${model.level == 4}"></h4>
<h5 th:text="${model.title}" th:if="${model.level == 5}"></h5>
<h6 th:text="${model.title}" th:if="${model.level == 6}"></h6>

Can this be done in a more clever way?

CodePudding user response:

Something like this would probably work but i doubt it be more readable and as such i would not recommend doing so. As debugging for a future dev might be more trouble than typing out all the ifs (or a switch) is.

<h1 id="placeholder">PLACEHOLDER<h1>

<script th:inline="javascript">
let element = /*[['h'   ${model.level}]]*/ "";
let $header = $(document.createElement(element));
$("#placeholder").replaceWith($header);
</script>

Do keep in mind that this is just mock code, it might have some typos but the idea should be correct

CodePudding user response:

You can use th:utext to output unescaped html. So something like this would work for example:

<th:block th:utext="|<h${model.level}>${model.title}</t${model.level}>|">

However, Thymeleaf wasn't really designed for this use case -- putting unescaped HTML into your templates is error prone and has security connotations (especially if you are taking in user input) and the template is hard to read now.

I would recommend just putting your original Thymeleaf into a fragment and using that.

HTML:

<th:block th:replace="index :: title(level=${model.level}, title=${model.title})" />

Fragment:

<th:block th:fragment="title(level, title)">
  <h1 th:text="${title}" th:if="${level == 1}"></h1>
  <h2 th:text="${title}" th:if="${level == 2}"></h2>
  <h3 th:text="${title}" th:if="${level == 3}"></h3>
  <h4 th:text="${title}" th:if="${level == 4}"></h4>
  <h5 th:text="${title}" th:if="${level == 5}"></h5>
  <h6 th:text="${title}" th:if="${level == 6}"></h6>
</th:block>
  • Related