2
votes

Users with different roles need to have different navbars at the top of the webpage. My topnavs are th:fragments, written in separate file, and that part of code works fine. But when I use th:switch and th:replace, all topnavs are shown in the webpage instead of just one.

I was looking these questions for solutions, but with no help:

Thymleaf switch statement with multiple case

How to use thymeleaf conditions - if - elseif - else

Things I tried:

<span th:if = "${role.value} == 'role1' " th:replace = "fragments/topnav :: navbar_role1"></span>
<span th:if = "${role.value} == 'role2' " th:replace = "fragments/topnav :: navbar_role2"></span>

#2

<span th:if = "${role} == 'role1' " th:replace = "fragments/topnav :: navbar_role1"></span>
<span th:if = "${role} == 'role2' " th:replace = "fragments/topnav :: navbar_role2"></span>

#3

<span th:if = "${role} eq 'role1' " th:replace = "fragments/topnav :: navbar_role1"></span>
<span th:if = "${role} eq 'role2' " th:replace = "fragments/topnav :: navbar_role2"></span

#4

<th:block th:switch = "${role}">
    <div th:case = "${role} eq 'role1' " th:replace = "fragments/topnav :: navbar_role1"></div>
    <div th:case = "${role} eq 'role2' " th:replace = "fragments/topnav :: navbar_role2"></div>
</th:block>

In debugger I can see in Java code that field role of type String has value role2. Instead of just second navbar, it shows both navbars. It must be that I missed something in Thymeleaf syntax?

1

1 Answers

1
votes

The target fragment needs to be in a child element, in this case, for the replace to work as intended.

Assume we have the following fragments in fragments/topnav.html:

<div th:fragment="navbar_role1">
    <div>This is navbar role 1</div>
</div>
<div th:fragment="navbar_role2">
    <div>This is navbar role 2</div>
</div>

Then your main page can be structured as follows:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>Switch Demo</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">        
    </head>
    <body>
        <th:block th:switch="${role}">
            <th:block th:case="'role1'">
                <div th:replace="fragments/topnav :: navbar_role1"></div>
            </th:block>
            <th:block th:case="'role2'">
                <div th:replace="fragments/topnav :: navbar_role2"></div>
            </th:block>
        </th:block>
    </body>
</html>

You can obviously use th:block elements or something else such as <div> elements, depending on what you want the final structure to look like.

Note also that you do not need the following when using a th:switch:

th:case="${role} eq 'role1'" // NOT needed

You can simply use the value itself:

th:case="'role1'"

That is one of the benefits of using switch statements here.