I have implemented pagation in my Spring boot application. There are no problems in the logic of it, however I am running into a weird issue with Thymeleaf.
Right now if I go to the following url
http://localhost:8080/Phoenix-listings
and if I hover my mouse over the link to page 2 is
http://localhost:8080/2
which is the wrong link, but if I manually go to the following url
http://localhost:8080/Phoenix-listings/1
then if I hover my mouse over page 2, then the link is
http://localhost:8080/Phoenix-listings/2
which is how it should be.
How can I make the correct link get generated even if I am in http://localhost:8080/Phoenix-listings?
Below is the section related to my pagation in Thymeleaf
<div class="row">
<div th:if="${ads.totalPages != 1}"
class="form-group col-md-11 pagination-centered">
<ul class="pagination">
<li th:class="${ads.number == 0} ? disabled"><a
class="pageLink" th:href="1">«</a></li>
<li th:class="${ads.number == 0} ? disabled"><a
class="pageLink" th:href="${ads.number}">←</a></li>
<li
th:class="${ads.number == (page - 1)} ? 'active pointer-disabled'"
th:each="page : ${#numbers.sequence(pager.startPage, pager.endPage)}">
<a class="pageLink" th:href="${page}" th:text="${page}"></a>
</li>
<li th:class="${ads.number + 1 == ads.totalPages} ? disabled">
<a class="pageLink" th:href="${ads.number + 2}">→</a>
</li>
<li th:class="${ads.number + 1 == ads.totalPages} ? disabled">
<a class="pageLink" th:href="${ads.totalPages}">»</a>
</li>
</ul>
</div>
</div>
In this case, you should be using thymeleaf's built in url syntax. It would look like this:
th:href="#{/{page}(page=${page})}"
Creating a link with #{/} means that thymeleaf automatically adds the context (Phoenix-listings in your case.) {page} is a placeholder. (page=${page}) replaces the placeholder with the variable.
You can also use string concatenation, but I wouldn't recommend it in most cases (because using the standard syntax means thymeleaf can correctly encode urls).
th:href="#{${'/' + page}}"
Related
I have a ul tag in thymeleaf and I have a li tag in it,and what I want is if one of the elements (which is amount here) is not null, show it, and what I want to show is something like the code below, which of course is wrong. How can I do this?
<li th:text="${ <th:if="ingredient.amount!=null> ingredient.amount"+
" "+ ingredient.uom.description"
</li>
If you alsways want to show a li (amount==null or amount!=null) then use a th:block with 2 li elements with a th:if-attribute where you check if the amount is null or not.
so lets say you have in your controller
model.addAttribute("ingredients",
List.of(
new Ingredient("3EL","Pepper"),
new Ingredient("500gr","Cheese"),
new Ingredient(null,"Salt")
)
);
then in your page
<th:block th:each="ingredient:${ingredients}">
<li th:if="${ingredient.amount != null}"
th:text="${ingredient.amount + ' of ' + ingredient.description}"></li>
<li th:if="${ingredient.amount == null}"
th:text="${'no need tu use ' + ingredient.description}"></li>
</th:block>
will generate
<ul>
<li>3EL of Pepper</li>
<li>500gr of Cheese</li>
<li>no need tu use Salt</li>
</ul>
if you only want to display the li where the amount is not null then you don't need the th:block
<ul>
<li th:each="ingredient:${ingredients}"
th:if="${ingredient.amount != null}"
th:text="${ingredient.amount + ' of ' + ingredient.description}" ></li>
</ul>
The way thymeleaf conditions work if an IF condition is false, tag and all tags inside of it will not be displayed.
so this must be what you were looking for:
<li th:if="${ingredient.amount != null}">
<ul th:text="${your.text}"></ul>
</li>
I'm making an E-commerce website and in the products section (inside admin), I was trying to display only 10 products per page. I'm new to Spring and while writing the code, I encountered an error (given in title) when trying to add the next page button. However, the code works fine with the Previous button and all the page numbers. Here's my code for the pagnation section:
<nav class="mt-3" th:if="${count > perPage}">
<ul class="pagination">
<li class="page-item" th:if="${page > 0}">
<a th:href="#{${#httpServletRequest.requestURI}} + '?page=__${page-1}__'" class="page-link">Previous</a>
</li>
<li class="page-item" th:each="number: ${#numbers.sequence(0, pageCount-1)}" th:classappend="${page==number} ? 'active' : ''">
<a th:href="#{${#httpServletRequest.requestURI}} + '?page=__${number}__'" class="page-link" th:text="${number+1}"></a>
</li>
<li class="page-item" th:if="${page pageCount-1}">
<a th:href="#{${#httpServletRequest.requestURI}} + '?page=__${page+1}__'" class="page-link">Next</a>
</li>
</ul>
</nav>
The first 2 li's work fine and I get the list of pages and also the previous button. But on adding the Next button, I get the error mentioned above.
First of all, please always provide the actual error message. Otherwise we are just guessing.
My guess is that th:if expects a boolean expression and what you have doesn't look like boolean to me: th:if="${page pageCount-1}"
Change that to something like page == pageCount-1, but again depends on what you want to display there
Defined constants in my class and using in UI to validate if user have the authority, show the menu to user else hide it. refer below code the way I implemented.
<li sec:authorize="hasAuthority('${T(com.sample.application.security.Privilege).ADMIN}')" class="nav-item" th:classappend="${template} == 'Home' ? 'active':''">
However, its not working as I expect. I was expecting thymeleaf to transform ${T(com.sample.application.security.Privilege).ADMIN} to ADMIN and verify it as hasAuthority('ADMIN') but thats not working. Is there any other way to do this validation in thymeleaf. Whats the best approach to get this implemented?
Update: Tried with assigning the constants to thymeleaf local variable as well. Didnt work either.
<ul class="navbar-nav" th:with="admin=${T(com.sample.application.security.Privilege).ADMINISTRATOR}, groupAdmin=${T(com.sample.application.security.Privilege).APPLICATION_GROUP_ADMIN}, basicUser=${T(com.sample.application.security.Privilege).APPLICATION_BASIC_USER}" >
<li sec:authorize="hasAuthority(${basicUser}) OR hasAuthority(${admin})" class="nav-item" th:classappend="${template} == 'home' ? 'active':''">
<a class="nav-link" href="/myApplication/User">Customer Home</a>
</li>......</ul>
After trying several ways. Below solution worked without any issue.
<ul class="navbar-nav">
<li sec:authorize="${hasAuthority(T(com.sample.application.security.Privilege).ADMINISTRATOR) OR hasAuthority(T(com.sample.application.security.Privilege).APPLICATION_GROUP_ADMIN)}" class="nav-item" th:classappend="${template} == 'home' ? 'active':''">
<a class="nav-link" href="/myApplication/User">Customer Home</a>
</li>
i have a nav bar that i am using as a template.. see pic
if i am on any of the tabs then i want home to show. But if i am on the home page i don't want Home tab to show its redundant. i cant seem to figure out how to write the thymleaf code..
i have something like this the first line is what i am interested in fixing... can you please help with the controller part also i am sure i can do a model.addAttribute line in each method call and set the isActive to true except the home method i can set the isActive to false ... thank you
li th:text="${isActive} ? 'Home : "
<li th:text="${isActive} ? '<a th:href="#{/}">Home</a> : " </li>
<li><a th:href="#{/about}">About</a></li>
<li class="auctions">Auctions <i class="fas fa-caret-down"></i>
<ul>
<li>Current Auctions</li>
<li>Register</li>
</ul>
</li>
<li><a th:href="#{/contact}">Contact</a></li>
<li><a th:href="#{/locations}">Locations</a></li>
you can use this in controller:
model.addAttribute("isActive",true);
and use this in html code:
<li th:if="${isActive == null || !isActive}"><a th:href="#{/}">Home</a></li>
read more about Conditionals in Thymeleaf and simple conditionals if and unless
I wanted to display navigation element as active (class nav-item active) when that element is clicked and the other elements with the non active class (nav-item). I am also using Thymeleaf layouts.
In the controller i have following code
#GetMapping("/login")
public String getLoginPage(Model model) {
model.addAttribute("activeLink", "Login");
return "login";
}
In the layout.html file (this file contains common header and footer for all pages), i have following code
<nav th:replace="navigation.html :: navibar(activeLink=${activeLink})"></nav>
In the navigation.html (this file only has navigation related code), i have code similar to
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top" th:fragment="navibar(activeLink)">
<a class="navbar-brand" href="/title">Title</a>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li th:class="${#strings.equals(activeLink, 'Home')} ? 'nav-item active' : 'nav-item'"><a class="nav-link" href="/">Home<span class="sr-only">(current)</span></a></li>
<li th:class="${#strings.equals(activeLink, 'Register')} ? 'nav-item active' : 'nav-item'"><a class="nav-link" href="/register">Register</a></li>
<li th:class="${#strings.equals(activeLink, 'Login')} ? 'nav-item active' : 'nav-item'" sec:authorize="isAnonymous()"><a class="nav-link" th:href="#{/login}">Login <span class="sr-only">(current)</span></a></li>
<li class="nav-item active" sec:authorize="isAuthenticated()"><a class="nav-link" th:href="#{/logout}">Logout <span class="sr-only">(current)</span></a></li>
</ul>
</div>
In the template returned by the controller (login), I do not have any navigation links specific code.
The above code is working, but is there a better simpler way to active navigation items?
Also, if I use flash attributes
redirectAttributes.addFlashAttribute("activeLink", "Register");
in the controller, then the functionality doesn't work
To avoid adding the activeLink to the model you can pass the activeLink when you include the fragment.
Like:
<div th:replace="nagivation :: navibar('Login')"></div>
Btw. you can remove the .html after the layout name.