i have a problem with Spring Boot Thymeleaf. I want to include a simple html-file in another html file with Thymeleaf.
Here my main.html file:
In the middle of the codesnippet you can see the root-div, here i want to include the dashboard.html file.
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Admin-Area</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="/backend/webjars/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link href="/backend/webjars/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 fixed-top mainnav navbar-expand-xl">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="../dashboard/dashboard.html">B2C-Shop</a>
<button type="button" class="navbar-toggler navbar-toggler-right">
<span class="navbar-toggler-icon"></span>
</button>
</nav>
<div class="container-fluid">
<div class="row">
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<div th:each="script: ${scripts}">
<div th:if="${script.endsWith('dashboard.html')}">
<div id="root" th:include="dashboard :: dashboard></div>
</div>
</div>
</main>
</div>
</div>
<script src="/backend/webjars/es5-shim/4.5.9/es5-shim.min.js"></script>
<script src="/backend/webjars/es6-shim/0.20.2/es6-shim.min.js"></script>
<script src="/backend/webjars/jquery/3.3.1/jquery.min.js"></script>
<script src="/backend/webjars/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="/backend/webjars/modernizr/2.8.3/modernizr.min.js"></script>
<div th:each="script: ${scripts}">
<div th:if="${script.endsWith('.js')}">
<script type="text/javascript" th:src="'/backend/js' + ${script}"></script>
</div>
</div>
</body>
</html>
And this is the dashboard.html file which i want to include in the main.html file.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div th:fragment="dashboard">
<h1>Welcome to B2C-Admin-Area</h1>
</div>
</html>
This is my DashboardController.java which i declare the dashboarb/dashboard.html file
The return methode "getTemplate()" references to backend folder in resources folder.
/**
*
* Render dash board
*
* #param model the attribute model
* #return the template file name
*/
#RequestMapping(value = "/backend/dashboard/dashboard.html", method = RequestMethod.GET)
public String dashboard(final Model model)
{
String[] script = {"/dashboard/dashboard.html"};
model.addAttribute(SCRIPT, script);
return getTemplate();
}
/**
* Gets the template file name.
*
* #return the template file name
*/
protected String getTemplate()
{
return "backend";
}
My folder stucture looks like this:
Do you have any idea to include this file?
Thank you.
Regards MWC.
First arrange your html files as shown in the below structure:
Then create fragment for import as :
suppose you saved below code in breadcrumb file in template/common folder:
<section class="content-header" th:fragment="breadcrumbfragment">
<ol class="breadcrumb">
<li><i class="fa fa-dashboard"></i> Home</li>
<li class="active">Next </li>
<li class="active">Next to Next</li>
</ol>
</section>
Now to import above fragment use following line:
<section class="content-header" th:replace="common/breadcrumb::breadcrumbfragment"></section>
Related
This question already has answers here:
Calling a servlet from JSP file on page load
(4 answers)
Generate an HTML Response in a Java Servlet
(3 answers)
Closed 2 months ago.
I have this problem where I am trying to get items from an ArrayList from a servlet and display it to a JSP file but when I try to get the variables from the item in the ArrayList, they don't show up.
Here is my JSP file
<?xml version="1.0" encoding="UTF-8" ?>
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# page import="java.util.*"%>
<%# page import="com.product.Product"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<script src="https://kit.fontawesome.com/256fd9e75f.js"
crossorigin="anonymous"></script>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap#4.1.3/dist/css/bootstrap.min.css"
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
crossorigin="anonymous" />
<link rel="stylesheet" href="styles.css" />
<title>Home</title>
<link rel="icon" href="src/ShopLogo.png" type="image/x-icon" />
</head>
<body>
<nav class="navbar fixed-top navbar-expand-md navbar-light"
style="background-color: #f15c55"> <span
class="navbar-brand mb-0 h1">Store</span>
<button type="button" data-toggle="collapse" data-target="#navbarNav"
class="navbar-toggler" aria-controls="navbarNav" aria-expanded="false"
aria-label="Toggle Nav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active"><a href="ProductLoaderServlet"
class="nav-link">Home</a></li>
<li class="nav-item active"><a href="product.html"
class="nav-link">Top Products</a></li>
<li class="nav-item active"><a href="cart.html" class="nav-link"><i
class="fa-regular fa-cart-shopping"></i></a></li>
</ul>
</div>
</nav>
<div class="image-overlay">
<img src="scr/main/resources/Shop.jpg" alt="" />
<h1 class="centered">Shop</h1>
</div>
<%
ArrayList<Product> products = (ArrayList) request.getAttribute("products");
for (Product product : products) {
%>
<div class="cards">
<div class="card" style="width: 18rem">
<img class="card-img-top" src="<%product.getImgUrl();%>" alt="Image" />
<div class="card-body">
<h5 class="card-title">
<%
product.getName();
%>
</h5>
Details
</div>
</div>
</div>
<%
}
%>
</body>
</html>
and this is what I see My View
I assume that I am able to get the items because I can see 5 cards
But I want to know why my variables such as (name, or the image) aren't showing up
Many Thanks for your help
I am using handlebar as a templating framework.
When the template get compiled, in case it is not well-formed html, there should be exception thrown.
Does handlebar have such a feature?
For example the following template is not well-formed as the img tag is not properly closed.
<head>
<meta charset="utf-8"/>
<title>Template</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col">
<img src="logo.jpg">
</div>
</div>
</div>
</body>
</html>
I have a Spring Boot Web MVC application where I'm using a Bootstrap 4 template and Thymeleaf as view.
I'm facing a problem where a drop-down navigation item is rendering without styles and scripts when the containing page is mapped in the controller under more than one path segment. If the path consists only of one segment the component works as intended.
Page containing the component "menu.html"
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Menu</title>
<!-- Custom fonts for this template -->
<link href="/vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template -->
<link href="/css/sb-admin-2.min.css" rel="stylesheet">
<!-- Custom styles for this page -->
<link href="/vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<ul class="navbar-nav ml-auto">
<!-- Drop-Down Component -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small" th:text="${user.getName()}"></span>
<img class="img-profile rounded-circle" src="img/undraw_profile.svg" width="50" height="50">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="logoutModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="logoutModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="/login?logout=true">Logout</a>
</div>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
<!-- Page level plugins -->
<script src="vendor/datatables/jquery.dataTables.min.js"></script>
<script src="vendor/datatables/dataTables.bootstrap4.min.js"></script>
<!-- Page level custom scripts -->
<script src="js/demo/datatables-demo.js"></script>
</body>
</html>
Using the following mapping in my controller the component works fine:
#GetMapping(value = "/first-segment")
public String showModal(Model model) {
model.addAttribute("user", userService.getAuthenticatedUser());
return "menu";
}
But if I add a second segment no styling is displayed and the component can't be clicked on:
#GetMapping(value = "/first-segment/second-segment")
public String showModal(Model model) {
model.addAttribute("user", userService.getAuthenticatedUser());
return "menu";
}
Note
I'd also like to add that not all Bootstrap components don't render correctly under two path segments. As far as I've noticed only drop-down and modal components share this issue.
Replace:
<script src="vendor/jquery/jquery.min.js"></script>
with:
<script src="/vendor/jquery/jquery.min.js"></script>
Note the extra slash at the start. Otherwise, the Javascript file is supposed to be relative to the current file. That is why it worked for the first segment, but not the second segment.
By starting with a slash, it is always relative to the root of the path.
I'm having trouble putting a button into the element of the list based on Thymeleaf. I would like to have a button next to element of the list.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout.html}">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
<section layout:fragment="" content="">
<div class="row">
<div class="col-2">
<a th:href="#{/archives}">archiwum zadań</a>
</div>
<div class="col-2">
<a th:href="#{/add}">dodawanie zadania</a>
</div>
</div>
<ul>
<li th:each="task: ${tasks}"
th:text="|${task.getId()} ${task.getName()} ${task.getCategory().getDescription()} ${task.isFinished()}|">
<input type="submit" value="Done">
</li>
</ul>
</section>
</body>
</html>
Thymeleaf will replace any pre-existing tag content with whatever is generated by the th:text expression.
In your case that pre-existing content is your <input> element - which is why the buttons are not displayed.
One way to avoid this is to place your th:text into a span inside the <li>:
<ul>
<li th:each="task: ${tasks}">
<span th:text="|${task.id} ${task.name} ... |"></span>
<input type="submit" value="Done">
</li>
</ul>
(I removed a couple of your fields from my example, for brevity).
Note also in my case, I have changed ${task.getId} to ${task.id}. As long as you have appropriately named getters (as per the JavaBeans naming convention) you can use the field name - and Thymeleaf will find the correct getter to call.
I'm using Spring-boot and thymeleaf and I'm trying to create a registration page but I can't seem to get to register.html from my login page
From the controller I have the following
#Controller
public class LoginController {
private final UserService userService;
#Autowired
public LoginController(UserService userService) {
this.userService = userService;
}
#RequestMapping(value = {"/login"}, method = {GET})
public ModelAndView login() {
return new ModelAndView("/login");
}
#RequestMapping(value = "/register", method = GET)
public ModelAndView register() {
System.out.println("register");
return new ModelAndView("register").addObject(new User());
}
For my login page I have this and it renders properly without an issue
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Log in</title>
<meta
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
name="viewport">
<link rel="stylesheet"
href="../static/style/bootstrap/bootstrap.min.css"/>
<link rel="stylesheet"
href="../static/style/font-awesome/font-awesome.min.css"/>
<link rel="stylesheet" href="../static/style/ionicons/ionicons.min.css"/>
<link rel="stylesheet" href="../static/style/adminlte/AdminLTE.min.css"/>
<link rel="stylesheet" href="../static/style/skins/skin-yellow.css"/>
<link rel="stylesheet" href="../static/style/custom.css"/>
</head>
<body class="hold-transition login-page">
<div class="login-box">
<div class="login-logo">
<b>Login</b>
</div>
<div class="login-box-body">
<p class="login-box-msg">Sign in</p>
<form th:action="#{/login}" method="post">
<div class="form-group has-feedback">
<input type="email" class="form-control" placeholder="Email"
name="username"> <span
class="glyphicon glyphicon-envelope form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input type="password" class="form-control" placeholder="Password"
name="password"> <span
class="fa fa-pencil form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<div class="col-md-4"></div>
<div class="col-md-8">
<button type="submit" class="btn btn-primary btn-block btn-flat"
style="margin-bottom: 10px;">Sign In
</button>
</div>
</div>
<br>
<p class="mb-0">
<a th:href="#{/register}">Sign Up</a>
</p>
<p class="mb-0">
<a th:href="#{/forgotPassword}">I forgot my password</a><br>
</p>
</form>
</div>
<div th:if="${param.error != null}">
<div id="error">
<div class="box-body">
<div class="alert alert-danger alert-dismissible">
<button type="submit" class="close" data-dismiss="alert"
aria-hidden="true">×
</button>
<h4>
<i class="icon fa fa-ban"></i>Login Failed!
</h4>
You have entered incorrect credentials please try again
</div>
</div>
</div>
</div>
</div>
<script src="../static/js/jquery/jquery.min.js"></script>
<script src="../static/js/bootstrap/bootstrap.min.js"></script>
<script src="../static/js/adminlte/adminlte.min.js"></script>
</body>
</html>
As I said, it's working fine
For my register page I have this
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Registration Page</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet"
href="../static/style/bootstrap/bootstrap.min.css"/>
<link rel="stylesheet"
href="../static/style/font-awesome/font-awesome.min.css"/>
<link rel="stylesheet" href="../static/style/ionicons/ionicons.min.css"/>
<link rel="stylesheet" href="../static/style/adminlte/AdminLTE.min.css"/>
<link rel="stylesheet" href="../static/style/skins/skin-yellow.css"/>
<link rel="stylesheet" href="../static/style/custom.css"/>
</head>
<body class="hold-transition register-page">
<div class="register-box">
<div class="register-logo">
<b>Registration</b>
</div>
<div class="card">
<div class="card-body register-card-body">
<p class="login-box-msg">Register a new membership</p>
<form th:object="user" method="get">
<p>Show something</p>
</form>
</div>
</div>
</div>
<script src="../static/js/jquery/jquery.min.js"></script>
<script src="../static/js/bootstrap/bootstrap.min.js"></script>
<script src="../static/js/adminlte/adminlte.min.js"></script>
</body>
</html>
But when I click on <a th:href="#{/register}">Sign Up</a> in my login page, it seems that the page only refreshes and isn't going to the register page, as you can see I tried printing something in the register() method of the LoginContoller but even this isn't printing which tells me my method is never hit, on closer inspection in the browser devtools, I saw that the register page is returning a 302 status as seen in the picture
I tried using a String return type in the controller but that doesn't work either.
I also tried to get the page without any objects being sent to it but that doesn't work.
How do I fix this?
I found the problem, in my SecurityConfig I referenced the wrong page name
.antMatchers(
"/static/**",
"/forgot/*",
"/actuator/*",
"/register")//this was wrong